VirtualBox

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

Last change on this file since 90488 was 90248, checked in by vboxsync, 3 years ago

ValidationKit: Enable Intel IOMMU (VT-d) smoketest as well since AC'97 issue was resolved in r145786.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 93.7 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxtestvms.py 90248 2021-07-20 07:24:03Z vboxsync $
3
4"""
5VirtualBox Test VMs
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2010-2020 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: 90248 $"
30
31# Standard Python imports.
32import copy;
33import os;
34import re;
35import random;
36import socket;
37import string;
38import uuid;
39
40# Validation Kit imports.
41from testdriver import base;
42from testdriver import reporter;
43from testdriver import vboxcon;
44from common import pathutils;
45from common import utils;
46
47
48# All virtualization modes.
49g_asVirtModes = ['hwvirt', 'hwvirt-np', 'raw',];
50# All virtualization modes except for raw-mode.
51g_asVirtModesNoRaw = ['hwvirt', 'hwvirt-np',];
52# Dictionary mapping the virtualization mode mnemonics to a little less cryptic
53# strings used in test descriptions.
54g_dsVirtModeDescs = {
55 'raw' : 'Raw-mode',
56 'hwvirt' : 'HwVirt',
57 'hwvirt-np' : 'NestedPaging'
58};
59
60## @name VM grouping flags
61## @{
62g_kfGrpSmoke = 0x0001; ##< Smoke test VM.
63g_kfGrpStandard = 0x0002; ##< Standard test VM.
64g_kfGrpStdSmoke = g_kfGrpSmoke | g_kfGrpStandard; ##< shorthand.
65g_kfGrpWithGAs = 0x0004; ##< The VM has guest additions installed.
66g_kfGrpNoTxs = 0x0008; ##< The VM lacks test execution service.
67g_kfGrpAncient = 0x1000; ##< Ancient OS.
68g_kfGrpExotic = 0x2000; ##< Exotic OS.
69## @}
70
71
72## @name Flags.
73## @{
74g_k32 = 32; # pylint: disable=invalid-name
75g_k64 = 64; # pylint: disable=invalid-name
76g_k32_64 = 96; # pylint: disable=invalid-name
77g_kiArchMask = 96;
78g_kiNoRaw = 128; ##< No raw mode.
79## @}
80
81# Array indexes.
82g_iGuestOsType = 0;
83g_iKind = 1;
84g_iFlags = 2;
85g_iMinCpu = 3;
86g_iMaxCpu = 4;
87g_iRegEx = 5;
88
89# Table translating from VM name core to a more detailed guest info.
90# pylint: disable=line-too-long
91## @todo what's the difference between the first two columns again?
92g_aaNameToDetails = \
93[
94 [ 'WindowsNT3x', 'WindowsNT3x', g_k32, 1, 32, ['nt3', 'nt3[0-9]*']], # max cpus??
95 [ 'WindowsNT4', 'WindowsNT4', g_k32, 1, 32, ['nt4', 'nt4sp[0-9]']], # max cpus??
96 [ 'Windows2000', 'Windows2000', g_k32, 1, 32, ['w2k', 'w2ksp[0-9]', 'win2k', 'win2ksp[0-9]']], # max cpus??
97 [ 'WindowsXP', 'WindowsXP', g_k32, 1, 32, ['xp', 'xpsp[0-9]']],
98 [ 'WindowsXP_64', 'WindowsXP_64', g_k64, 1, 32, ['xp64', 'xp64sp[0-9]']],
99 [ 'Windows2003', 'Windows2003', g_k32, 1, 32, ['w2k3', 'w2k3sp[0-9]', 'win2k3', 'win2k3sp[0-9]']],
100 [ 'WindowsVista', 'WindowsVista', g_k32, 1, 32, ['vista', 'vistasp[0-9]']],
101 [ 'WindowsVista_64','WindowsVista_64', g_k64, 1, 64, ['vista-64', 'vistasp[0-9]-64',]], # max cpus/cores??
102 [ 'Windows2008', 'Windows2008', g_k32, 1, 64, ['w2k8', 'w2k8sp[0-9]', 'win2k8', 'win2k8sp[0-9]']], # max cpus/cores??
103 [ 'Windows2008_64', 'Windows2008_64', g_k64, 1, 64, ['w2k8r2', 'w2k8r2sp[0-9]', 'win2k8r2', 'win2k8r2sp[0-9]']], # max cpus/cores??
104 [ 'Windows7', 'Windows7', g_k32, 1, 32, ['w7', 'w7sp[0-9]', 'win7',]], # max cpus/cores??
105 [ 'Windows7_64', 'Windows7_64', g_k64, 1, 64, ['w7-64', 'w7sp[0-9]-64', 'win7-64',]], # max cpus/cores??
106 [ 'Windows8', 'Windows8', g_k32 | g_kiNoRaw, 1, 32, ['w8', 'w8sp[0-9]', 'win8',]], # max cpus/cores??
107 [ 'Windows8_64', 'Windows8_64', g_k64, 1, 64, ['w8-64', 'w8sp[0-9]-64', 'win8-64',]], # max cpus/cores??
108 [ 'Windows81', 'Windows81', g_k32 | g_kiNoRaw, 1, 32, ['w81', 'w81sp[0-9]', 'win81',]], # max cpus/cores??
109 [ 'Windows81_64', 'Windows81_64', g_k64, 1, 64, ['w81-64', 'w81sp[0-9]-64', 'win81-64',]], # max cpus/cores??
110 [ 'Windows10', 'Windows10', g_k32 | g_kiNoRaw, 1, 32, ['w10', 'w10sp[0-9]', 'win10',]], # max cpus/cores??
111 [ 'Windows10_64', 'Windows10_64', g_k64, 1, 64, ['w10-64', 'w10sp[0-9]-64', 'win10-64',]], # max cpus/cores??
112 [ 'Linux', 'Debian', g_k32, 1, 256, ['deb[0-9]*', 'debian[0-9]*', ]],
113 [ 'Linux_64', 'Debian_64', g_k64, 1, 256, ['deb[0-9]*-64', 'debian[0-9]*-64', ]],
114 [ 'Linux', 'RedHat', g_k32, 1, 256, ['rhel', 'rhel[0-9]', 'rhel[0-9]u[0-9]']],
115 [ 'Linux', 'Fedora', g_k32, 1, 256, ['fedora', 'fedora[0-9]*', ]],
116 [ 'Linux_64', 'Fedora_64', g_k64, 1, 256, ['fedora-64', 'fedora[0-9]*-64', ]],
117 [ 'Linux', 'Oracle', g_k32, 1, 256, ['ols[0-9]*', 'oel[0-9]*', ]],
118 [ 'Linux_64', 'Oracle_64', g_k64, 1, 256, ['ols[0-9]*-64', 'oel[0-9]*-64', ]],
119 [ 'Linux', 'OpenSUSE', g_k32, 1, 256, ['opensuse[0-9]*', 'suse[0-9]*', ]],
120 [ 'Linux_64', 'OpenSUSE_64', g_k64, 1, 256, ['opensuse[0-9]*-64', 'suse[0-9]*-64', ]],
121 [ 'Linux', 'Ubuntu', g_k32, 1, 256, ['ubuntu[0-9]*', ]],
122 [ 'Linux_64', 'Ubuntu_64', g_k64, 1, 256, ['ubuntu[0-9]*-64', ]],
123 [ 'Linux', 'ArchLinux', g_k32, 1, 256, ['arch[0-9]*', ]],
124 [ 'Linux_64', 'ArchLinux_64', g_k64, 1, 256, ['arch[0-9]*-64', ]],
125 [ 'Solaris', 'Solaris', g_k32, 1, 256, ['sol10', 'sol10u[0-9]']],
126 [ 'Solaris_64', 'Solaris_64', g_k64, 1, 256, ['sol10-64', 'sol10u-64[0-9]']],
127 [ 'Solaris_64', 'Solaris11_64', g_k64, 1, 256, ['sol11u1']],
128 [ 'BSD', 'FreeBSD_64', g_k32_64, 1, 1, ['bs-.*']], # boot sectors, wanted 64-bit type.
129 [ 'DOS', 'DOS', g_k32, 1, 1, ['bs-.*']],
130];
131
132
133## @name Guest OS type string constants.
134## @{
135g_ksGuestOsTypeDarwin = 'darwin';
136g_ksGuestOsTypeDOS = 'dos';
137g_ksGuestOsTypeFreeBSD = 'freebsd';
138g_ksGuestOsTypeLinux = 'linux';
139g_ksGuestOsTypeOS2 = 'os2';
140g_ksGuestOsTypeSolaris = 'solaris';
141g_ksGuestOsTypeWindows = 'windows';
142## @}
143
144## @name String constants for paravirtualization providers.
145## @{
146g_ksParavirtProviderNone = 'none';
147g_ksParavirtProviderDefault = 'default';
148g_ksParavirtProviderLegacy = 'legacy';
149g_ksParavirtProviderMinimal = 'minimal';
150g_ksParavirtProviderHyperV = 'hyperv';
151g_ksParavirtProviderKVM = 'kvm';
152## @}
153
154## Valid paravirtualization providers.
155g_kasParavirtProviders = ( g_ksParavirtProviderNone, g_ksParavirtProviderDefault, g_ksParavirtProviderLegacy,
156 g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM );
157
158# Mapping for support of paravirtualisation providers per guest OS.
159#g_kdaParavirtProvidersSupported = {
160# g_ksGuestOsTypeDarwin : ( g_ksParavirtProviderMinimal, ),
161# g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, ),
162# g_ksGuestOsTypeLinux : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
163# g_ksGuestOsTypeOS2 : ( g_ksParavirtProviderNone, ),
164# g_ksGuestOsTypeSolaris : ( g_ksParavirtProviderNone, ),
165# g_ksGuestOsTypeWindows : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, )
166#}
167# Temporary tweak:
168# since for the most guests g_ksParavirtProviderNone is almost the same as g_ksParavirtProviderMinimal,
169# g_ksParavirtProviderMinimal is removed from the list in order to get maximum number of unique choices
170# during independent test runs when paravirt provider is taken randomly.
171g_kdaParavirtProvidersSupported = {
172 g_ksGuestOsTypeDarwin : ( g_ksParavirtProviderMinimal, ),
173 g_ksGuestOsTypeDOS : ( g_ksParavirtProviderNone, ),
174 g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, ),
175 g_ksGuestOsTypeLinux : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
176 g_ksGuestOsTypeOS2 : ( g_ksParavirtProviderNone, ),
177 g_ksGuestOsTypeSolaris : ( g_ksParavirtProviderNone, ),
178 g_ksGuestOsTypeWindows : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, )
179}
180
181
182# pylint: enable=line-too-long
183
184def _intersects(asSet1, asSet2):
185 """
186 Checks if any of the strings in set 1 matches any of the regular
187 expressions in set 2.
188 """
189 for sStr1 in asSet1:
190 for sRx2 in asSet2:
191 if re.match(sStr1, sRx2 + '$'):
192 return True;
193 return False;
194
195
196
197class BaseTestVm(object):
198 """
199 Base class for Test VMs.
200 """
201
202 def __init__(self, # pylint: disable=too-many-arguments
203 sVmName, # type: str
204 fGrouping = 0, # type: int
205 oSet = None, # type: TestVmSet
206 sKind = None, # type: str
207 acCpusSup = None, # type: List[int]
208 asVirtModesSup = None, # type: List[str]
209 asParavirtModesSup = None, # type: List[str]
210 fRandomPvPModeCrap = False, # type: bool
211 fVmmDevTestingPart = None, # type: bool
212 fVmmDevTestingMmio = False, # type: bool
213 iGroup = 1, # type: int
214 ):
215 self.oSet = oSet # type: TestVmSet
216 self.sVmName = sVmName;
217 self.iGroup = iGroup; # Startup group (for MAC address uniqueness and non-NAT networking).
218 self.fGrouping = fGrouping;
219 self.sKind = sKind; # API Guest OS type.
220 self.acCpusSup = acCpusSup;
221 self.asVirtModesSup = asVirtModesSup;
222 self.asParavirtModesSup = asParavirtModesSup;
223 self.asParavirtModesSupOrg = asParavirtModesSup; # HACK ALERT! Trick to make the 'effing random mess not get in the
224 # way of actively selecting virtualization modes.
225
226 self.fSkip = False; # All VMs are included in the configured set by default.
227 self.fSnapshotRestoreCurrent = False; # Whether to restore execution on the current snapshot.
228
229 # VMMDev and serial (TXS++) settings:
230 self.fVmmDevTestingPart = fVmmDevTestingPart;
231 self.fVmmDevTestingMmio = fVmmDevTestingMmio;
232 self.fCom1RawFile = False;
233
234 # Cached stuff (use getters):
235 self.__sCom1RawFile = None; # Set by createVmInner and getReconfiguredVm if fCom1RawFile is set.
236 self.__tHddCtrlPortDev = (None, None, None); # The HDD controller, port and device.
237 self.__tDvdCtrlPortDev = (None, None, None); # The DVD controller, port and device.
238 self.__cbHdd = -1; # The recommended HDD size.
239
240 # Derived stuff:
241 self.aInfo = None;
242 self.sGuestOsType = None; # ksGuestOsTypeXxxx value, API GuestOS Type is in the sKind member.
243 ## @todo rename sGuestOsType
244 self._guessStuff(fRandomPvPModeCrap);
245
246 def _mkCanonicalGuestOSType(self, sType):
247 """
248 Convert guest OS type into constant representation.
249 Raise exception if specified @param sType is unknown.
250 """
251 if sType.lower().startswith('darwin'):
252 return g_ksGuestOsTypeDarwin
253 if sType.lower().startswith('bsd'):
254 return g_ksGuestOsTypeFreeBSD
255 if sType.lower().startswith('dos'):
256 return g_ksGuestOsTypeDOS
257 if sType.lower().startswith('linux'):
258 return g_ksGuestOsTypeLinux
259 if sType.lower().startswith('os2'):
260 return g_ksGuestOsTypeOS2
261 if sType.lower().startswith('solaris'):
262 return g_ksGuestOsTypeSolaris
263 if sType.lower().startswith('windows'):
264 return g_ksGuestOsTypeWindows
265 raise base.GenError(sWhat="unknown guest OS kind: %s" % str(sType))
266
267 def _guessStuff(self, fRandomPvPModeCrap):
268 """
269 Used by the constructor to guess stuff.
270 """
271
272 sNm = self.sVmName.lower().strip();
273 asSplit = sNm.replace('-', ' ').split(' ');
274
275 if self.sKind is None:
276 # From name.
277 for aInfo in g_aaNameToDetails:
278 if _intersects(asSplit, aInfo[g_iRegEx]):
279 self.aInfo = aInfo;
280 self.sGuestOsType = self._mkCanonicalGuestOSType(aInfo[g_iGuestOsType])
281 self.sKind = aInfo[g_iKind];
282 break;
283 if self.sKind is None:
284 reporter.fatal('The OS of test VM "%s" cannot be guessed' % (self.sVmName,));
285
286 # Check for 64-bit, if required and supported.
287 if (self.aInfo[g_iFlags] & g_kiArchMask) == g_k32_64 and _intersects(asSplit, ['64', 'amd64']):
288 self.sKind = self.sKind + '_64';
289 else:
290 # Lookup the kind.
291 for aInfo in g_aaNameToDetails:
292 if self.sKind == aInfo[g_iKind]:
293 self.aInfo = aInfo;
294 break;
295 if self.aInfo is None:
296 reporter.fatal('The OS of test VM "%s" with sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
297
298 # Translate sKind into sGuest OS Type.
299 if self.sGuestOsType is None:
300 if self.aInfo is not None:
301 self.sGuestOsType = self._mkCanonicalGuestOSType(self.aInfo[g_iGuestOsType])
302 elif self.sKind.find("Windows") >= 0:
303 self.sGuestOsType = g_ksGuestOsTypeWindows
304 elif self.sKind.find("Linux") >= 0:
305 self.sGuestOsType = g_ksGuestOsTypeLinux;
306 elif self.sKind.find("Solaris") >= 0:
307 self.sGuestOsType = g_ksGuestOsTypeSolaris;
308 elif self.sKind.find("DOS") >= 0:
309 self.sGuestOsType = g_ksGuestOsTypeDOS;
310 else:
311 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
312
313 # Restrict modes and such depending on the OS.
314 if self.asVirtModesSup is None:
315 self.asVirtModesSup = list(g_asVirtModes);
316 if self.sGuestOsType in (g_ksGuestOsTypeOS2, g_ksGuestOsTypeDarwin) \
317 or self.sKind.find('_64') > 0 \
318 or (self.aInfo is not None and (self.aInfo[g_iFlags] & g_kiNoRaw)):
319 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
320 # TEMPORARY HACK - START
321 sHostName = os.environ.get("COMPUTERNAME", None);
322 if sHostName: sHostName = sHostName.lower();
323 else: sHostName = socket.getfqdn(); # Horribly slow on windows without IPv6 DNS/whatever.
324 if sHostName.startswith('testboxpile1'):
325 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
326 # TEMPORARY HACK - END
327
328 # Restrict the CPU count depending on the OS and/or percieved SMP readiness.
329 if self.acCpusSup is None:
330 if _intersects(asSplit, ['uni']):
331 self.acCpusSup = [1];
332 elif self.aInfo is not None:
333 self.acCpusSup = list(range(self.aInfo[g_iMinCpu], self.aInfo[g_iMaxCpu]));
334 else:
335 self.acCpusSup = [1];
336
337 # Figure relevant PV modes based on the OS.
338 if self.asParavirtModesSup is None:
339 self.asParavirtModesSup = g_kdaParavirtProvidersSupported[self.sGuestOsType];
340 ## @todo Remove this hack as soon as we've got around to explictly configure test variations
341 ## on the server side. Client side random is interesting but not the best option.
342 self.asParavirtModesSupOrg = self.asParavirtModesSup;
343 if fRandomPvPModeCrap:
344 random.seed();
345 self.asParavirtModesSup = (random.choice(self.asParavirtModesSup),);
346
347 return True;
348
349 def _generateRawPortFilename(self, oTestDrv, sInfix, sSuffix):
350 """ Generates a raw port filename. """
351 random.seed();
352 sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10));
353 return os.path.join(oTestDrv.sScratchPath, self.sVmName + sInfix + sRandom + sSuffix);
354
355 def _createVmPre(self, oTestDrv, eNic0AttachType, sDvdImage):
356 """
357 Prepares for creating the VM.
358
359 Returns True / False.
360 """
361 _ = eNic0AttachType; _ = sDvdImage;
362 if self.fCom1RawFile:
363 self.__sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
364 return True;
365
366 def _createVmDoIt(self, oTestDrv, eNic0AttachType, sDvdImage):
367 """
368 Creates the VM.
369
370 The default implementation creates a VM with defaults, no disks created or attached.
371
372 Returns Wrapped VM object on success, None on failure.
373 """
374 return oTestDrv.createTestVmWithDefaults(self.sVmName,
375 iGroup = self.iGroup,
376 sKind = self.sKind,
377 eNic0AttachType = eNic0AttachType,
378 sDvdImage = sDvdImage,
379 fVmmDevTestingPart = self.fVmmDevTestingPart,
380 fVmmDevTestingMmio = self.fVmmDevTestingMmio,
381 sCom1RawFile = self.__sCom1RawFile if self.fCom1RawFile else None
382 );
383
384 def _createVmPost(self, oTestDrv, oVM, eNic0AttachType, sDvdImage): # type: (base.testdriver, Any, int, str) -> Any
385 """
386 Returns same oVM on success, None on failure (createVm cleans up).
387 """
388 _ = oTestDrv; _ = eNic0AttachType; _ = sDvdImage;
389 return oVM;
390
391 def _skipVmTest(self, oTestDrv, oVM):
392 """
393 Called by getReconfiguredVm to figure out whether to skip the VM or not.
394
395 Returns True if the VM should be skipped, False otherwise.
396 """
397 _ = oVM;
398 fHostSupports64bit = oTestDrv.hasHostLongMode();
399 if self.is64bitRequired() and not fHostSupports64bit:
400 reporter.log('Skipping 64-bit VM on non-64 capable host.');
401 elif self.isViaIncompatible() and oTestDrv.isHostCpuVia():
402 reporter.log('Skipping VIA incompatible VM.');
403 elif self.isShanghaiIncompatible() and oTestDrv.isHostCpuShanghai():
404 reporter.log('Skipping Shanghai (Zhaoxin) incompatible VM.');
405 elif self.isP4Incompatible() and oTestDrv.isHostCpuP4():
406 reporter.log('Skipping P4 incompatible VM.');
407 else:
408 return False;
409 return True;
410
411
412 def _childVmReconfig(self, oTestDrv, oVM, oSession):
413 """
414 Hook into getReconfiguredVm() for children.
415 """
416 _ = oTestDrv; _ = oVM; _ = oSession;
417 return True;
418
419 def _storageCtrlAndBusToName(self, oVBoxMgr, oVM, eCtrl, eBus):
420 """
421 Resolves the storage controller name given type and bus.
422
423 Returns String on success, None on failure w/ errors logged.
424 """
425 try:
426 aoControllers = oVBoxMgr.getArray(oVM, 'storageControllers');
427 except:
428 reporter.errorXcpt();
429 return None;
430 asSummary = [];
431 for oController in aoControllers:
432 try:
433 eCurCtrl = oController.controllerType;
434 eCurBus = oController.bus;
435 sName = oController.name;
436 except:
437 reporter.errorXcpt();
438 return None;
439 if eCurCtrl == eCtrl and eCurBus == eBus:
440 return sName;
441 asSummary.append('%s-%s-%s' % (eCurCtrl, eCurBus, sName,));
442 reporter.error('Unable to find controller of type %s and bus %s (searched: %s)' % (eCtrl, eBus, ', '.join(asSummary),));
443 return None;
444
445
446 #
447 # Public interface.
448 #
449
450 def getResourceSet(self):
451 """
452 Resturns a list of reosurces that the VM needs.
453 """
454 return [];
455
456 def getMissingResources(self, sResourcePath):
457 """
458 Returns a list of missing resources (paths, stuff) that the VM needs.
459 """
460 asRet = [];
461 asResources = self.getResourceSet();
462 for sPath in asResources:
463 if not os.path.isabs(sPath):
464 sPath = os.path.join(sResourcePath, sPath);
465 if not os.path.exists(sPath):
466 asRet.append(sPath);
467 return asRet;
468
469 def skipCreatingVm(self, oTestDrv):
470 """
471 Called before VM creation to determine whether the VM should be skipped
472 due to host incompatibility or something along those lines.
473
474 returns True if it should be skipped, False if not. Caller updates fSkip.
475
476 See also _skipVmTest().
477 """
478 _ = oTestDrv;
479 return False;
480
481
482 def createVm(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
483 """
484 Creates the VM with defaults and the few tweaks as per the arguments.
485
486 Returns same as vbox.TestDriver.createTestVM.
487 """
488 reporter.log2('');
489 reporter.log2('Creating %s...' % (self.sVmName,))
490 oVM = None;
491 fRc = self._createVmPre(oTestDrv, eNic0AttachType, sDvdImage);
492 if fRc is True:
493 oVM = self._createVmDoIt(oTestDrv, eNic0AttachType, sDvdImage);
494 if oVM:
495 oVM = self._createVmPost(oTestDrv, oVM, eNic0AttachType, sDvdImage);
496 return oVM;
497
498 def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None):
499 """
500 actionExecute worker that finds and reconfigure a test VM.
501
502 Returns (fRc, oVM) where fRc is True, None or False and oVM is a
503 VBox VM object that is only present when rc is True.
504 """
505
506 fRc = False;
507 oVM = oTestDrv.getVmByName(self.sVmName);
508 if oVM is not None:
509 if self.fSnapshotRestoreCurrent is True:
510 fRc = True;
511 else:
512 fHostSupports64bit = oTestDrv.hasHostLongMode();
513 if self._skipVmTest(oTestDrv, oVM):
514 fRc = None; # Skip the test.
515 else:
516 oSession = oTestDrv.openSession(oVM);
517 if oSession is not None:
518 fRc = oSession.enableVirtEx(sVirtMode != 'raw');
519 fRc = fRc and oSession.enableNestedPaging(sVirtMode == 'hwvirt-np');
520 fRc = fRc and oSession.setCpuCount(cCpus);
521 if cCpus > 1:
522 fRc = fRc and oSession.enableIoApic(True);
523
524 if sParavirtMode is not None and oSession.fpApiVer >= 5.0:
525 adParavirtProviders = {
526 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None,
527 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default,
528 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy,
529 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal,
530 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV,
531 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM,
532 };
533 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]);
534
535 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw');
536 fRc = fRc and oSession.enableLongMode(fCfg64Bit);
537 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh.
538 oOsType = oSession.getOsType();
539 if oOsType is not None:
540 if oOsType.is64Bit and sVirtMode == 'raw':
541 assert(oOsType.id[-3:] == '_64');
542 fRc = fRc and oSession.setOsType(oOsType.id[:-3]);
543 elif not oOsType.is64Bit and sVirtMode != 'raw':
544 fRc = fRc and oSession.setOsType(oOsType.id + '_64');
545
546 # New serial raw file.
547 if fRc and self.fCom1RawFile:
548 self.__sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
549 utils.noxcptDeleteFile(self.__sCom1RawFile);
550 fRc = oSession.setupSerialToRawFile(0, self.__sCom1RawFile);
551
552 # Make life simpler for child classes.
553 if fRc:
554 fRc = self._childVmReconfig(oTestDrv, oVM, oSession);
555
556 fRc = fRc and oSession.saveSettings();
557 if not oSession.close():
558 fRc = False;
559 if fRc is True:
560 return (True, oVM);
561 return (fRc, None);
562
563 def getNonCanonicalGuestOsType(self):
564 """
565 Gets the non-canonical OS type (self.sGuestOsType is canonical).
566 """
567 return self.sKind; #self.aInfo[g_iGuestOsType];
568
569 def getGuestArch(self):
570 """ Same as util.getHostArch. """
571 return 'amd64' if self.sKind.find('_64') >= 0 else 'x86';
572
573 def getGuestOs(self):
574 """ Same as util.getHostOs. """
575 if self.isWindows(): return 'win';
576 if self.isOS2(): return 'os2';
577 if self.isLinux(): return 'linux';
578 reporter.error('getGuestOs does not what to return!');
579 raise Exception();
580
581 def getGuestOsDotArch(self):
582 """ Same as util.getHostOsDotArch. """
583 return self.getGuestOs() + '.' + self.getGuestArch();
584
585 def getGuestExeSuff(self):
586 """ The executable image suffix for the guest. """
587 if self.isWindows() or self.isOS2():
588 return '.exe';
589 return '';
590
591 def isWindows(self):
592 """ Checks if it's a Windows VM. """
593 return self.sGuestOsType == g_ksGuestOsTypeWindows;
594
595 def isOS2(self):
596 """ Checks if it's an OS/2 VM. """
597 return self.sGuestOsType == g_ksGuestOsTypeOS2;
598
599 def isLinux(self):
600 """ Checks if it's an Linux VM. """
601 return self.sGuestOsType == g_ksGuestOsTypeLinux;
602
603 def is64bit(self):
604 """ Checks if it's a 64-bit VM. """
605 return self.sKind.find('_64') >= 0;
606
607 def is64bitRequired(self):
608 """ Check if 64-bit is required or not. """
609 return (self.aInfo[g_iFlags] & g_k64) != 0;
610
611 def isLoggedOntoDesktop(self):
612 """ Checks if the test VM is logging onto a graphical desktop by default. """
613 if self.isWindows():
614 return True;
615 if self.isOS2():
616 return True;
617 if self.sVmName.find('-desktop'):
618 return True;
619 return False;
620
621 def isViaIncompatible(self):
622 """
623 Identifies VMs that doesn't work on VIA.
624
625 Returns True if NOT supported on VIA, False if it IS supported.
626 """
627 # Oracle linux doesn't like VIA in our experience
628 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
629 return True;
630 # OS/2: "The system detected an internal processing error at location
631 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
632 if self.isOS2():
633 return True;
634 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
635 # detected, leading to a STOP 3e(80,0,0,0).
636 if self.aInfo[g_iKind] == 'WindowsNT4':
637 if self.sVmName.find('sp') < 0:
638 return True; # no service pack.
639 if self.sVmName.find('sp0') >= 0 \
640 or self.sVmName.find('sp1') >= 0 \
641 or self.sVmName.find('sp2') >= 0 \
642 or self.sVmName.find('sp3') >= 0:
643 return True;
644 # XP x64 on a physical VIA box hangs exactly like a VM.
645 if self.aInfo[g_iKind] in ['WindowsXP_64', 'Windows2003_64']:
646 return True;
647 # Vista 64 throws BSOD 0x5D (UNSUPPORTED_PROCESSOR)
648 if self.aInfo[g_iKind] in ['WindowsVista_64']:
649 return True;
650 # Solaris 11 hangs on VIA, tested on a physical box (testboxvqc)
651 if self.aInfo[g_iKind] in ['Solaris11_64']:
652 return True;
653 return False;
654
655 def isShanghaiIncompatible(self):
656 """
657 Identifies VMs that doesn't work on Shanghai.
658
659 Returns True if NOT supported on Shanghai, False if it IS supported.
660 """
661 # For now treat it just like VIA, to be adjusted later
662 return self.isViaIncompatible()
663
664 def isP4Incompatible(self):
665 """
666 Identifies VMs that doesn't work on Pentium 4 / Pentium D.
667
668 Returns True if NOT supported on P4, False if it IS supported.
669 """
670 # Stupid 1 kHz timer. Too much for antique CPUs.
671 if self.sVmName.find('rhel5') >= 0:
672 return True;
673 # Due to the boot animation the VM takes forever to boot.
674 if self.aInfo[g_iKind] == 'Windows2000':
675 return True;
676 return False;
677
678 def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv):
679 """
680 Checks if the host OS is affected by older ubuntu installers being very
681 picky about which families of AMD CPUs it would run on.
682
683 The installer checks for family 15, later 16, later 20, and in 11.10
684 they remove the family check for AMD CPUs.
685 """
686 if not oTestDrv.isHostCpuAmd():
687 return False;
688 try:
689 (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0);
690 (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0);
691 except:
692 reporter.logXcpt();
693 return False;
694 if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff:
695 return False;
696
697 uFamily = (uFamilyModel >> 8) & 0xf
698 if uFamily == 0xf:
699 uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf;
700 ## @todo Break this down into which old ubuntu release supports exactly
701 ## which AMD family, if we care.
702 if uFamily <= 15:
703 return False;
704 reporter.log('Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.'
705 % (self.sVmName, uFamily,));
706 return True;
707
708 def getTestUser(self):
709 """
710 Gets the primary test user name.
711 """
712 if self.isWindows():
713 return 'Administrator';
714 return 'vbox';
715
716 def getTestUserPassword(self, sUser = None):
717 """
718 Gets the password for the primary user (or other specified one).
719 """
720 if sUser == 'test':
721 return '';
722 if sUser == 'vboxuser': # Default unattended installation user and password.
723 return 'changeme';
724 return 'password';
725
726 def getCom1RawFile(self, oVM):
727 """
728 Gets the name of the COM1 raw file.
729
730 Returns string, None on failure or if not active.
731
732 Note! Do not access __sCom1RawFile directly as it will not be set unless the
733 'config' action was executed in the same run.
734 """
735 if self.fCom1RawFile:
736 # Retrieve it from the IMachine object and cache the result if needed:
737 if self.__sCom1RawFile is None:
738 try:
739 oPort = oVM.machine.getSerialPort(0);
740 except:
741 reporter.errorXcpt('failed to get serial port #0');
742 else:
743 try:
744 self.__sCom1RawFile = oPort.path;
745 except:
746 reporter.errorXcpt('failed to get the "path" property on serial port #0');
747 return self.__sCom1RawFile;
748
749 reporter.error('getCom1RawFile called when fCom1RawFile is False');
750 return None;
751
752 def getIGuestOSType(self, oVBoxWrapped):
753 """
754 Gets the IGuestOSType object corresponding to self.sKind.
755
756 Returns object on success, None on failure (logged as error).
757 """
758 try:
759 return oVBoxWrapped.o.getGuestOSType(self.sKind);
760 except:
761 reporter.errorXcpt('sVmName=%s sKind=%s' % (self.sVmName, self.sKind,));
762 return None;
763
764 def getRecommendedHddSize(self, oVBoxWrapped):
765 """
766 Gets the recommended HDD size from the IGuestOSType matching self.sKind.
767
768 Returns size in bytes on success, -1 on failure.
769 """
770 if self.__cbHdd < 0:
771 oGuestOSType = self.getIGuestOSType(oVBoxWrapped);
772 if oGuestOSType:
773 try:
774 self.__cbHdd = oGuestOSType.recommendedHDD;
775 except:
776 reporter.errorXcpt();
777 return -1;
778 return self.__cbHdd;
779
780 def getHddAddress(self, oVM, oVBoxWrapped):
781 """
782 Gets the HDD attachment address.
783
784 Returns (sController, iPort, iDevice) on success; (None, None, None) on failure.
785
786 Note! Do not access the cached value directly!
787 """
788 # Cached already?
789 if self.__tHddCtrlPortDev[0] is not None:
790 return self.__tHddCtrlPortDev;
791
792 # First look for HDs attached to the VM:
793 try:
794 aoAttachments = oVBoxWrapped.oVBoxMgr.getArray(oVM, 'mediumAttachments')
795 except:
796 reporter.errorXcpt();
797 else:
798 for oAtt in aoAttachments:
799 try:
800 sCtrl = oAtt.controller
801 iPort = oAtt.port;
802 iDev = oAtt.device;
803 eType = oAtt.type;
804 except:
805 reporter.errorXcpt();
806 return self.__tHddCtrlPortDev;
807 if eType == vboxcon.DeviceType_HardDisk:
808 self.__tHddCtrlPortDev = (sCtrl, iPort, iDev);
809 reporter.log2('getHddAddress: %s, %s, %s' % self.__tHddCtrlPortDev);
810 return self.__tHddCtrlPortDev;
811
812 # Then consult IGuestOSType:
813 oGuestOSType = self.getIGuestOSType(oVBoxWrapped);
814 if oGuestOSType:
815 try:
816 eCtrl = oGuestOSType.recommendedHDStorageController;
817 eBus = oGuestOSType.recommendedHDStorageBus;
818 except:
819 reporter.errorXcpt();
820 else:
821 # ASSUMES port 0, device 0.
822 self.__tHddCtrlPortDev = (self._storageCtrlAndBusToName(oVBoxWrapped.oVBoxMgr, oVM, eCtrl, eBus), 0, 0);
823 reporter.log2('getHddAddress: %s, %s, %s [IGuestOSType]' % self.__tHddCtrlPortDev);
824 return self.__tHddCtrlPortDev;
825
826 def getDvdAddress(self, oVM, oVBoxWrapped):
827 """
828 Gets the DVD attachment address.
829
830 Returns (sController, iPort, iDevice) on success; (None, None, None) on failure.
831
832 Note! Do not access the cached value directly!
833 """
834 # Cached already?
835 if self.__tDvdCtrlPortDev[0] is not None:
836 return self.__tDvdCtrlPortDev;
837
838 # First look for DVD attached to the VM:
839 try:
840 aoAttachments = oVBoxWrapped.oVBoxMgr.getArray(oVM, 'mediumAttachments')
841 except:
842 reporter.errorXcpt();
843 else:
844 for oAtt in aoAttachments:
845 try:
846 sCtrl = oAtt.controller
847 iPort = oAtt.port;
848 iDev = oAtt.device;
849 eType = oAtt.type;
850 except:
851 reporter.errorXcpt();
852 return self.__tDvdCtrlPortDev;
853 if eType == vboxcon.DeviceType_DVD:
854 self.__tDvdCtrlPortDev = (sCtrl, iPort, iDev);
855 reporter.log2('getDvdAddress: %s, %s, %s' % self.__tDvdCtrlPortDev);
856 return self.__tDvdCtrlPortDev;
857
858 # Then consult IGuestOSType:
859 oGuestOSType = self.getIGuestOSType(oVBoxWrapped);
860 if oGuestOSType:
861 try:
862 eCtrl = oGuestOSType.recommendedDVDStorageController;
863 eBus = oGuestOSType.recommendedDVDStorageBus;
864 except:
865 reporter.errorXcpt();
866 else:
867 # ASSUMES port 1, device 0.
868 self.__tDvdCtrlPortDev = (self._storageCtrlAndBusToName(oVBoxWrapped.oVBoxMgr, oVM, eCtrl, eBus), 1, 0);
869 reporter.log2('getDvdAddress: %s, %s, %s [IGuestOSType]' % self.__tDvdCtrlPortDev);
870 return self.__tDvdCtrlPortDev;
871
872 def recreateRecommendedHdd(self, oVM, oTestDrv, sHddPath = None):
873 """
874 Detaches and delete any current hard disk and then ensures that a new
875 one with the recommended size is created and attached to the recommended
876 controller/port/device.
877
878 Returns True/False (errors logged).
879 """
880 # Generate a name if none was given:
881 if not sHddPath:
882 try:
883 sHddPath = oVM.settingsFilePath;
884 except:
885 return reporter.errorXcpt();
886 sHddPath = os.path.join(os.path.dirname(sHddPath), '%s-%s.vdi' % (self.sVmName, uuid.uuid4(),));
887
888 fRc = False;
889
890 # Get the hard disk specs first:
891 cbHdd = self.getRecommendedHddSize(oTestDrv.oVBox);
892 tHddAddress = self.getHddAddress(oVM, oTestDrv.oVBox);
893 assert len(tHddAddress) == 3;
894 if tHddAddress[0] and cbHdd > 0:
895 # Open an session so we can make changes:
896 oSession = oTestDrv.openSession(oVM);
897 if oSession is not None:
898 # Detach the old disk (this will succeed with oOldHd set to None the first time around).
899 (fRc, oOldHd) = oSession.detachHd(tHddAddress[0], tHddAddress[1], tHddAddress[2]);
900 if fRc:
901 # Create a new disk and attach it.
902 fRc = oSession.createAndAttachHd(sHddPath,
903 cb = cbHdd,
904 sController = tHddAddress[0],
905 iPort = tHddAddress[1],
906 iDevice = tHddAddress[2],
907 fImmutable = False);
908 if fRc:
909 # Save the changes.
910 fRc = oSession.saveSettings();
911
912 # Delete the old HD:
913 if fRc and oOldHd is not None:
914 fRc = fRc and oTestDrv.oVBox.deleteHdByMedium(oOldHd);
915 fRc = fRc and oSession.saveSettings(); # Necessary for media reg??
916 else:
917 oSession.discardSettings();
918 fRc = oSession.close() and fRc;
919 return fRc;
920
921 def pathJoin(self, sBase, *asAppend):
922 """ See common.pathutils.joinEx(). """
923 return pathutils.joinEx(self.isWindows() or self.isOS2(), sBase, *asAppend);
924
925 def pathSep(self):
926 """ Returns the preferred paths separator for the guest OS. """
927 return '\\' if self.isWindows() or self.isOS2() else '/';
928
929
930## @todo Inherit from BaseTestVm
931class TestVm(object):
932 """
933 A Test VM - name + VDI/whatever.
934
935 This is just a data object.
936 """
937
938 def __init__(self, # pylint: disable=too-many-arguments
939 sVmName, # type: str
940 fGrouping = 0, # type: int
941 oSet = None, # type: TestVmSet
942 sHd = None, # type: str
943 sKind = None, # type: str
944 acCpusSup = None, # type: List[int]
945 asVirtModesSup = None, # type: List[str]
946 fIoApic = None, # type: bool
947 fNstHwVirt = False, # type: bool
948 fPae = None, # type: bool
949 sNic0AttachType = None, # type: str
950 sFloppy = None, # type: str
951 fVmmDevTestingPart = None, # type: bool
952 fVmmDevTestingMmio = False, # type: bool
953 asParavirtModesSup = None, # type: List[str]
954 fRandomPvPMode = False, # type: bool
955 sFirmwareType = 'bios', # type: str
956 sChipsetType = 'piix3', # type: str
957 sIommuType = 'none', # type: str
958 sHddControllerType = 'IDE Controller', # type: str
959 sDvdControllerType = 'IDE Controller' # type: str
960 ):
961 self.oSet = oSet;
962 self.sVmName = sVmName;
963 self.fGrouping = fGrouping;
964 self.sHd = sHd; # Relative to the testrsrc root.
965 self.acCpusSup = acCpusSup;
966 self.asVirtModesSup = asVirtModesSup;
967 self.asParavirtModesSup = asParavirtModesSup;
968 self.asParavirtModesSupOrg = asParavirtModesSup; # HACK ALERT! Trick to make the 'effing random mess not get in the
969 # way of actively selecting virtualization modes.
970 self.sKind = sKind;
971 self.sGuestOsType = None;
972 self.sDvdImage = None; # Relative to the testrsrc root.
973 self.sDvdControllerType = sDvdControllerType;
974 self.fIoApic = fIoApic;
975 self.fNstHwVirt = fNstHwVirt;
976 self.fPae = fPae;
977 self.sNic0AttachType = sNic0AttachType;
978 self.sHddControllerType = sHddControllerType;
979 self.sFloppy = sFloppy; # Relative to the testrsrc root, except when it isn't...
980 self.fVmmDevTestingPart = fVmmDevTestingPart;
981 self.fVmmDevTestingMmio = fVmmDevTestingMmio;
982 self.sFirmwareType = sFirmwareType;
983 self.sChipsetType = sChipsetType;
984 self.sIommuType = sIommuType;
985 self.fCom1RawFile = False;
986
987 self.fSnapshotRestoreCurrent = False; # Whether to restore execution on the current snapshot.
988 self.fSkip = False; # All VMs are included in the configured set by default.
989 self.aInfo = None;
990 self.sCom1RawFile = None; # Set by createVmInner and getReconfiguredVm if fCom1RawFile is set.
991 self._guessStuff(fRandomPvPMode);
992
993 def _mkCanonicalGuestOSType(self, sType):
994 """
995 Convert guest OS type into constant representation.
996 Raise exception if specified @param sType is unknown.
997 """
998 if sType.lower().startswith('darwin'):
999 return g_ksGuestOsTypeDarwin
1000 if sType.lower().startswith('bsd'):
1001 return g_ksGuestOsTypeFreeBSD
1002 if sType.lower().startswith('dos'):
1003 return g_ksGuestOsTypeDOS
1004 if sType.lower().startswith('linux'):
1005 return g_ksGuestOsTypeLinux
1006 if sType.lower().startswith('os2'):
1007 return g_ksGuestOsTypeOS2
1008 if sType.lower().startswith('solaris'):
1009 return g_ksGuestOsTypeSolaris
1010 if sType.lower().startswith('windows'):
1011 return g_ksGuestOsTypeWindows
1012 raise base.GenError(sWhat="unknown guest OS kind: %s" % str(sType))
1013
1014 def _guessStuff(self, fRandomPvPMode):
1015 """
1016 Used by the constructor to guess stuff.
1017 """
1018
1019 sNm = self.sVmName.lower().strip();
1020 asSplit = sNm.replace('-', ' ').split(' ');
1021
1022 if self.sKind is None:
1023 # From name.
1024 for aInfo in g_aaNameToDetails:
1025 if _intersects(asSplit, aInfo[g_iRegEx]):
1026 self.aInfo = aInfo;
1027 self.sGuestOsType = self._mkCanonicalGuestOSType(aInfo[g_iGuestOsType])
1028 self.sKind = aInfo[g_iKind];
1029 break;
1030 if self.sKind is None:
1031 reporter.fatal('The OS of test VM "%s" cannot be guessed' % (self.sVmName,));
1032
1033 # Check for 64-bit, if required and supported.
1034 if (self.aInfo[g_iFlags] & g_kiArchMask) == g_k32_64 and _intersects(asSplit, ['64', 'amd64']):
1035 self.sKind = self.sKind + '_64';
1036 else:
1037 # Lookup the kind.
1038 for aInfo in g_aaNameToDetails:
1039 if self.sKind == aInfo[g_iKind]:
1040 self.aInfo = aInfo;
1041 break;
1042 if self.aInfo is None:
1043 reporter.fatal('The OS of test VM "%s" with sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
1044
1045 # Translate sKind into sGuest OS Type.
1046 if self.sGuestOsType is None:
1047 if self.aInfo is not None:
1048 self.sGuestOsType = self._mkCanonicalGuestOSType(self.aInfo[g_iGuestOsType])
1049 elif self.sKind.find("Windows") >= 0:
1050 self.sGuestOsType = g_ksGuestOsTypeWindows
1051 elif self.sKind.find("Linux") >= 0:
1052 self.sGuestOsType = g_ksGuestOsTypeLinux;
1053 elif self.sKind.find("Solaris") >= 0:
1054 self.sGuestOsType = g_ksGuestOsTypeSolaris;
1055 elif self.sKind.find("DOS") >= 0:
1056 self.sGuestOsType = g_ksGuestOsTypeDOS;
1057 else:
1058 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
1059
1060 # Restrict modes and such depending on the OS.
1061 if self.asVirtModesSup is None:
1062 self.asVirtModesSup = list(g_asVirtModes);
1063 if self.sGuestOsType in (g_ksGuestOsTypeOS2, g_ksGuestOsTypeDarwin) \
1064 or self.sKind.find('_64') > 0 \
1065 or (self.aInfo is not None and (self.aInfo[g_iFlags] & g_kiNoRaw)):
1066 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
1067 # TEMPORARY HACK - START
1068 sHostName = os.environ.get("COMPUTERNAME", None);
1069 if sHostName: sHostName = sHostName.lower();
1070 else: sHostName = socket.getfqdn(); # Horribly slow on windows without IPv6 DNS/whatever.
1071 if sHostName.startswith('testboxpile1'):
1072 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
1073 # TEMPORARY HACK - END
1074
1075 # Restrict the CPU count depending on the OS and/or percieved SMP readiness.
1076 if self.acCpusSup is None:
1077 if _intersects(asSplit, ['uni']):
1078 self.acCpusSup = [1];
1079 elif self.aInfo is not None:
1080 self.acCpusSup = list(range(self.aInfo[g_iMinCpu], self.aInfo[g_iMaxCpu]));
1081 else:
1082 self.acCpusSup = [1];
1083
1084 # Figure relevant PV modes based on the OS.
1085 if self.asParavirtModesSup is None:
1086 self.asParavirtModesSup = g_kdaParavirtProvidersSupported[self.sGuestOsType];
1087 ## @todo Remove this hack as soon as we've got around to explictly configure test variations
1088 ## on the server side. Client side random is interesting but not the best option.
1089 self.asParavirtModesSupOrg = self.asParavirtModesSup;
1090 if fRandomPvPMode:
1091 random.seed();
1092 self.asParavirtModesSup = (random.choice(self.asParavirtModesSup),);
1093
1094 return True;
1095
1096 def getNonCanonicalGuestOsType(self):
1097 """
1098 Gets the non-canonical OS type (self.sGuestOsType is canonical).
1099 """
1100 return self.aInfo[g_iGuestOsType];
1101
1102 def getMissingResources(self, sTestRsrc):
1103 """
1104 Returns a list of missing resources (paths, stuff) that the VM needs.
1105 """
1106 asRet = [];
1107 for sPath in [ self.sHd, self.sDvdImage, self.sFloppy]:
1108 if sPath is not None:
1109 if not os.path.isabs(sPath):
1110 sPath = os.path.join(sTestRsrc, sPath);
1111 if not os.path.exists(sPath):
1112 asRet.append(sPath);
1113 return asRet;
1114
1115 def skipCreatingVm(self, oTestDrv):
1116 """
1117 Called before VM creation to determine whether the VM should be skipped
1118 due to host incompatibility or something along those lines.
1119
1120 returns True if it should be skipped, False if not.
1121 """
1122 if self.fNstHwVirt and not oTestDrv.hasHostNestedHwVirt():
1123 reporter.log('Ignoring VM %s (Nested hardware-virtualization not support on this host).' % (self.sVmName,));
1124 return True;
1125 return False;
1126
1127 def createVm(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
1128 """
1129 Creates the VM with defaults and the few tweaks as per the arguments.
1130
1131 Returns same as vbox.TestDriver.createTestVM.
1132 """
1133 if sDvdImage is not None:
1134 sMyDvdImage = sDvdImage;
1135 else:
1136 sMyDvdImage = self.sDvdImage;
1137
1138 if eNic0AttachType is not None:
1139 eMyNic0AttachType = eNic0AttachType;
1140 elif self.sNic0AttachType is None:
1141 eMyNic0AttachType = None;
1142 elif self.sNic0AttachType == 'nat':
1143 eMyNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
1144 elif self.sNic0AttachType == 'bridged':
1145 eMyNic0AttachType = vboxcon.NetworkAttachmentType_Bridged;
1146 else:
1147 assert False, self.sNic0AttachType;
1148
1149 return self.createVmInner(oTestDrv, eMyNic0AttachType, sMyDvdImage);
1150
1151 def _generateRawPortFilename(self, oTestDrv, sInfix, sSuffix):
1152 """ Generates a raw port filename. """
1153 random.seed();
1154 sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10));
1155 return os.path.join(oTestDrv.sScratchPath, self.sVmName + sInfix + sRandom + sSuffix);
1156
1157 def createVmInner(self, oTestDrv, eNic0AttachType, sDvdImage):
1158 """
1159 Same as createVm but parameters resolved.
1160
1161 Returns same as vbox.TestDriver.createTestVM.
1162 """
1163 reporter.log2('');
1164 reporter.log2('Calling createTestVM on %s...' % (self.sVmName,))
1165 if self.fCom1RawFile:
1166 self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
1167 return oTestDrv.createTestVM(self.sVmName,
1168 1, # iGroup
1169 sHd = self.sHd,
1170 sKind = self.sKind,
1171 fIoApic = self.fIoApic,
1172 fNstHwVirt = self.fNstHwVirt,
1173 fPae = self.fPae,
1174 eNic0AttachType = eNic0AttachType,
1175 sDvdImage = sDvdImage,
1176 sDvdControllerType = self.sDvdControllerType,
1177 sHddControllerType = self.sHddControllerType,
1178 sFloppy = self.sFloppy,
1179 fVmmDevTestingPart = self.fVmmDevTestingPart,
1180 fVmmDevTestingMmio = self.fVmmDevTestingMmio,
1181 sFirmwareType = self.sFirmwareType,
1182 sChipsetType = self.sChipsetType,
1183 sIommuType = self.sIommuType,
1184 sCom1RawFile = self.sCom1RawFile if self.fCom1RawFile else None
1185 );
1186
1187 def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None):
1188 """
1189 actionExecute worker that finds and reconfigure a test VM.
1190
1191 Returns (fRc, oVM) where fRc is True, None or False and oVM is a
1192 VBox VM object that is only present when rc is True.
1193 """
1194
1195 fRc = False;
1196 oVM = oTestDrv.getVmByName(self.sVmName);
1197 if oVM is not None:
1198 if self.fSnapshotRestoreCurrent is True:
1199 fRc = True;
1200 else:
1201 fHostSupports64bit = oTestDrv.hasHostLongMode();
1202 if self.is64bitRequired() and not fHostSupports64bit:
1203 fRc = None; # Skip the test.
1204 elif self.isViaIncompatible() and oTestDrv.isHostCpuVia():
1205 fRc = None; # Skip the test.
1206 elif self.isShanghaiIncompatible() and oTestDrv.isHostCpuShanghai():
1207 fRc = None; # Skip the test.
1208 elif self.isP4Incompatible() and oTestDrv.isHostCpuP4():
1209 fRc = None; # Skip the test.
1210 else:
1211 oSession = oTestDrv.openSession(oVM);
1212 if oSession is not None:
1213 fRc = oSession.enableVirtEx(sVirtMode != 'raw');
1214 fRc = fRc and oSession.enableNestedPaging(sVirtMode == 'hwvirt-np');
1215 fRc = fRc and oSession.setCpuCount(cCpus);
1216 if cCpus > 1:
1217 fRc = fRc and oSession.enableIoApic(True);
1218
1219 if sParavirtMode is not None and oSession.fpApiVer >= 5.0:
1220 adParavirtProviders = {
1221 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None,
1222 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default,
1223 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy,
1224 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal,
1225 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV,
1226 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM,
1227 };
1228 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]);
1229
1230 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw');
1231 fRc = fRc and oSession.enableLongMode(fCfg64Bit);
1232 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh.
1233 oOsType = oSession.getOsType();
1234 if oOsType is not None:
1235 if oOsType.is64Bit and sVirtMode == 'raw':
1236 assert(oOsType.id[-3:] == '_64');
1237 fRc = fRc and oSession.setOsType(oOsType.id[:-3]);
1238 elif not oOsType.is64Bit and sVirtMode != 'raw':
1239 fRc = fRc and oSession.setOsType(oOsType.id + '_64');
1240
1241 # New serial raw file.
1242 if fRc and self.fCom1RawFile:
1243 self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
1244 utils.noxcptDeleteFile(self.sCom1RawFile);
1245 fRc = oSession.setupSerialToRawFile(0, self.sCom1RawFile);
1246
1247 # Make life simpler for child classes.
1248 if fRc:
1249 fRc = self._childVmReconfig(oTestDrv, oVM, oSession);
1250
1251 fRc = fRc and oSession.saveSettings();
1252 if not oSession.close():
1253 fRc = False;
1254 if fRc is True:
1255 return (True, oVM);
1256 return (fRc, None);
1257
1258 def _childVmReconfig(self, oTestDrv, oVM, oSession):
1259 """ Hook into getReconfiguredVm() for children. """
1260 _ = oTestDrv; _ = oVM; _ = oSession;
1261 return True;
1262
1263 def getGuestArch(self):
1264 """ Same as util.getHostArch. """
1265 return 'amd64' if self.sKind.find('_64') >= 0 else 'x86';
1266
1267 def getGuestOs(self):
1268 """ Same as util.getHostOs. """
1269 if self.isWindows(): return 'win';
1270 if self.isOS2(): return 'os2';
1271 if self.isLinux(): return 'linux';
1272 reporter.error('getGuestOs does not what to return!');
1273 raise Exception();
1274
1275 def getGuestExeSuff(self):
1276 """ The executable image suffix for the guest. """
1277 if self.isWindows() or self.isOS2():
1278 return '.exe';
1279 return '';
1280
1281 def getGuestOsDotArch(self):
1282 """ Same as util.getHostOsDotArch."""
1283 return self.getGuestOs() + '.' + self.getGuestArch();
1284
1285 def isWindows(self):
1286 """ Checks if it's a Windows VM. """
1287 return self.sGuestOsType == g_ksGuestOsTypeWindows;
1288
1289 def isOS2(self):
1290 """ Checks if it's an OS/2 VM. """
1291 return self.sGuestOsType == g_ksGuestOsTypeOS2;
1292
1293 def isLinux(self):
1294 """ Checks if it's an Linux VM. """
1295 return self.sGuestOsType == g_ksGuestOsTypeLinux;
1296
1297 def is64bit(self):
1298 """ Checks if it's a 64-bit VM. """
1299 return self.sKind.find('_64') >= 0;
1300
1301 def is64bitRequired(self):
1302 """ Check if 64-bit is required or not. """
1303 return (self.aInfo[g_iFlags] & g_k64) != 0;
1304
1305 def isLoggedOntoDesktop(self):
1306 """ Checks if the test VM is logging onto a graphical desktop by default. """
1307 if self.isWindows():
1308 return True;
1309 if self.isOS2():
1310 return True;
1311 if self.sVmName.find('-desktop'):
1312 return True;
1313 return False;
1314
1315 def isViaIncompatible(self):
1316 """
1317 Identifies VMs that doesn't work on VIA.
1318
1319 Returns True if NOT supported on VIA, False if it IS supported.
1320 """
1321 # Oracle linux doesn't like VIA in our experience
1322 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
1323 return True;
1324 # OS/2: "The system detected an internal processing error at location
1325 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
1326 if self.isOS2():
1327 return True;
1328 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
1329 # detected, leading to a STOP 3e(80,0,0,0).
1330 if self.aInfo[g_iKind] == 'WindowsNT4':
1331 if self.sVmName.find('sp') < 0:
1332 return True; # no service pack.
1333 if self.sVmName.find('sp0') >= 0 \
1334 or self.sVmName.find('sp1') >= 0 \
1335 or self.sVmName.find('sp2') >= 0 \
1336 or self.sVmName.find('sp3') >= 0:
1337 return True;
1338 # XP x64 on a physical VIA box hangs exactly like a VM.
1339 if self.aInfo[g_iKind] in ['WindowsXP_64', 'Windows2003_64']:
1340 return True;
1341 # Vista 64 throws BSOD 0x5D (UNSUPPORTED_PROCESSOR)
1342 if self.aInfo[g_iKind] in ['WindowsVista_64']:
1343 return True;
1344 # Solaris 11 hangs on VIA, tested on a physical box (testboxvqc)
1345 if self.aInfo[g_iKind] in ['Solaris11_64']:
1346 return True;
1347 return False;
1348
1349 def isShanghaiIncompatible(self):
1350 """
1351 Identifies VMs that doesn't work on Shanghai.
1352
1353 Returns True if NOT supported on Shanghai, False if it IS supported.
1354 """
1355 # For now treat it just like VIA, to be adjusted later
1356 return self.isViaIncompatible()
1357
1358 def isP4Incompatible(self):
1359 """
1360 Identifies VMs that doesn't work on Pentium 4 / Pentium D.
1361
1362 Returns True if NOT supported on P4, False if it IS supported.
1363 """
1364 # Stupid 1 kHz timer. Too much for antique CPUs.
1365 if self.sVmName.find('rhel5') >= 0:
1366 return True;
1367 # Due to the boot animation the VM takes forever to boot.
1368 if self.aInfo[g_iKind] == 'Windows2000':
1369 return True;
1370 return False;
1371
1372 def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv):
1373 """
1374 Checks if the host OS is affected by older ubuntu installers being very
1375 picky about which families of AMD CPUs it would run on.
1376
1377 The installer checks for family 15, later 16, later 20, and in 11.10
1378 they remove the family check for AMD CPUs.
1379 """
1380 if not oTestDrv.isHostCpuAmd():
1381 return False;
1382 try:
1383 (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0);
1384 (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0);
1385 except:
1386 reporter.logXcpt();
1387 return False;
1388 if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff:
1389 return False;
1390
1391 uFamily = (uFamilyModel >> 8) & 0xf
1392 if uFamily == 0xf:
1393 uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf;
1394 ## @todo Break this down into which old ubuntu release supports exactly
1395 ## which AMD family, if we care.
1396 if uFamily <= 15:
1397 return False;
1398 reporter.log('Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.'
1399 % (self.sVmName, uFamily,));
1400 return True;
1401
1402 def getTestUser(self):
1403 """
1404 Gets the primary test user name.
1405 """
1406 if self.isWindows():
1407 return 'Administrator';
1408 return 'vbox';
1409
1410 def getTestUserPassword(self, sUser = None):
1411 """
1412 Gets the password for the primary user (or other specified one).
1413 """
1414 if sUser == 'test':
1415 return '';
1416 if sUser == 'vboxuser': # Default unattended installation user and password.
1417 return 'changeme';
1418 return 'password';
1419
1420 def pathJoin(self, sBase, *asAppend):
1421 """ See common.pathutils.joinEx(). """
1422 return pathutils.joinEx(self.isWindows() or self.isOS2(), sBase, *asAppend);
1423
1424 def pathSep(self):
1425 """ Returns the preferred paths separator for the guest OS. """
1426 return '\\' if self.isWindows() or self.isOS2() else '/';
1427
1428
1429class BootSectorTestVm(TestVm):
1430 """
1431 A Boot Sector Test VM.
1432 """
1433
1434 def __init__(self, oSet, sVmName, sFloppy = None, asVirtModesSup = None, f64BitRequired = False):
1435 self.f64BitRequired = f64BitRequired;
1436 if asVirtModesSup is None:
1437 asVirtModesSup = list(g_asVirtModes);
1438 TestVm.__init__(self, sVmName,
1439 oSet = oSet,
1440 acCpusSup = [1,],
1441 sFloppy = sFloppy,
1442 asVirtModesSup = asVirtModesSup,
1443 fPae = True,
1444 fIoApic = True,
1445 fVmmDevTestingPart = True,
1446 fVmmDevTestingMmio = True,
1447 );
1448
1449 def is64bitRequired(self):
1450 return self.f64BitRequired;
1451
1452
1453class AncientTestVm(TestVm):
1454 """
1455 A ancient Test VM, using the serial port for communicating results.
1456
1457 We're looking for 'PASSED' and 'FAILED' lines in the COM1 output.
1458 """
1459
1460
1461 def __init__(self, # pylint: disable=too-many-arguments
1462 sVmName, # type: str
1463 fGrouping = g_kfGrpAncient | g_kfGrpNoTxs, # type: int
1464 sHd = None, # type: str
1465 sKind = None, # type: str
1466 acCpusSup = None, # type: List[int]
1467 asVirtModesSup = None, # type: List[str]
1468 sNic0AttachType = None, # type: str
1469 sFloppy = None, # type: str
1470 sFirmwareType = 'bios', # type: str
1471 sChipsetType = 'piix3', # type: str
1472 sHddControllerName = 'IDE Controller', # type: str
1473 sDvdControllerName = 'IDE Controller', # type: str
1474 cMBRamMax = None, # type: int
1475 ):
1476 TestVm.__init__(self,
1477 sVmName,
1478 fGrouping = fGrouping,
1479 sHd = sHd,
1480 sKind = sKind,
1481 acCpusSup = [1] if acCpusSup is None else acCpusSup,
1482 asVirtModesSup = asVirtModesSup,
1483 sNic0AttachType = sNic0AttachType,
1484 sFloppy = sFloppy,
1485 sFirmwareType = sFirmwareType,
1486 sChipsetType = sChipsetType,
1487 sHddControllerType = sHddControllerName,
1488 sDvdControllerType = sDvdControllerName,
1489 asParavirtModesSup = (g_ksParavirtProviderNone,)
1490 );
1491 self.fCom1RawFile = True;
1492 self.cMBRamMax= cMBRamMax;
1493
1494
1495 def _childVmReconfig(self, oTestDrv, oVM, oSession):
1496 _ = oVM; _ = oTestDrv;
1497 fRc = True;
1498
1499 # DOS 4.01 doesn't like the default 32MB of memory.
1500 if fRc and self.cMBRamMax is not None:
1501 try:
1502 cMBRam = oSession.o.machine.memorySize;
1503 except:
1504 cMBRam = self.cMBRamMax + 4;
1505 if self.cMBRamMax < cMBRam:
1506 fRc = oSession.setRamSize(self.cMBRamMax);
1507
1508 return fRc;
1509
1510
1511class TestVmSet(object):
1512 """
1513 A set of Test VMs.
1514 """
1515
1516 def __init__(self, oTestVmManager = None, acCpus = None, asVirtModes = None, fIgnoreSkippedVm = False):
1517 self.oTestVmManager = oTestVmManager;
1518 if acCpus is None:
1519 acCpus = [1, 2];
1520 self.acCpusDef = acCpus;
1521 self.acCpus = acCpus;
1522 if asVirtModes is None:
1523 asVirtModes = list(g_asVirtModes);
1524 self.asVirtModesDef = asVirtModes;
1525 self.asVirtModes = asVirtModes;
1526 self.aoTestVms = [] # type: list(BaseTestVm)
1527 self.fIgnoreSkippedVm = fIgnoreSkippedVm;
1528 self.asParavirtModes = None; ##< If None, use the first PV mode of the test VM, otherwise all modes in this list.
1529
1530 def findTestVmByName(self, sVmName):
1531 """
1532 Returns the TestVm object with the given name.
1533 Returns None if not found.
1534 """
1535
1536 # The 'tst-' prefix is optional.
1537 sAltName = sVmName if sVmName.startswith('tst-') else 'tst-' + sVmName;
1538
1539 for oTestVm in self.aoTestVms:
1540 if oTestVm.sVmName == sVmName or oTestVm.sVmName == sAltName:
1541 return oTestVm;
1542 return None;
1543
1544 def getAllVmNames(self, sSep = ':'):
1545 """
1546 Returns names of all the test VMs in the set separated by
1547 sSep (defaults to ':').
1548 """
1549 sVmNames = '';
1550 for oTestVm in self.aoTestVms:
1551 sName = oTestVm.sVmName;
1552 if sName.startswith('tst-'):
1553 sName = sName[4:];
1554 if sVmNames == '':
1555 sVmNames = sName;
1556 else:
1557 sVmNames = sVmNames + sSep + sName;
1558 return sVmNames;
1559
1560 def showUsage(self):
1561 """
1562 Invoked by vbox.TestDriver.
1563 """
1564 reporter.log('');
1565 reporter.log('Test VM selection and general config options:');
1566 reporter.log(' --virt-modes <m1[:m2[:...]]>');
1567 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
1568 reporter.log(' --skip-virt-modes <m1[:m2[:...]]>');
1569 reporter.log(' Use this to avoid hwvirt or hwvirt-np when not supported by the host');
1570 reporter.log(' since we cannot detect it using the main API. Use after --virt-modes.');
1571 reporter.log(' --cpu-counts <c1[:c2[:...]]>');
1572 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
1573 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
1574 reporter.log(' Test the specified VMs in the given order. Use this to change');
1575 reporter.log(' the execution order or limit the choice of VMs');
1576 reporter.log(' Default: %s (all)' % (self.getAllVmNames(),));
1577 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
1578 reporter.log(' Skip the specified VMs when testing.');
1579 reporter.log(' --snapshot-restore-current');
1580 reporter.log(' Restores the current snapshot and resumes execution.');
1581 reporter.log(' --paravirt-modes <pv1[:pv2[:...]]>');
1582 reporter.log(' Set of paravirtualized providers (modes) to tests. Intersected with what the test VM supports.');
1583 reporter.log(' Default is the first PV mode the test VMs support, generally same as "legacy".');
1584 reporter.log(' --with-nested-hwvirt-only');
1585 reporter.log(' Test VMs using nested hardware-virtualization only.');
1586 reporter.log(' --without-nested-hwvirt-only');
1587 reporter.log(' Test VMs not using nested hardware-virtualization only.');
1588 ## @todo Add more options for controlling individual VMs.
1589 return True;
1590
1591 def parseOption(self, asArgs, iArg):
1592 """
1593 Parses the set test vm set options (--test-vms and --skip-vms), modifying the set
1594 Invoked by the testdriver method with the same name.
1595
1596 Keyword arguments:
1597 asArgs -- The argument vector.
1598 iArg -- The index of the current argument.
1599
1600 Returns iArg if the option was not recognized and the caller should handle it.
1601 Returns the index of the next argument when something is consumed.
1602
1603 In the event of a syntax error, a InvalidOption or QuietInvalidOption
1604 is thrown.
1605 """
1606
1607 if asArgs[iArg] == '--virt-modes':
1608 iArg += 1;
1609 if iArg >= len(asArgs):
1610 raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
1611
1612 self.asVirtModes = asArgs[iArg].split(':');
1613 for s in self.asVirtModes:
1614 if s not in self.asVirtModesDef:
1615 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
1616 % (s, ' '.join(self.asVirtModesDef)));
1617
1618 elif asArgs[iArg] == '--skip-virt-modes':
1619 iArg += 1;
1620 if iArg >= len(asArgs):
1621 raise base.InvalidOption('The "--skip-virt-modes" takes a colon separated list of modes');
1622
1623 for s in asArgs[iArg].split(':'):
1624 if s not in self.asVirtModesDef:
1625 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
1626 % (s, ' '.join(self.asVirtModesDef)));
1627 if s in self.asVirtModes:
1628 self.asVirtModes.remove(s);
1629
1630 elif asArgs[iArg] == '--cpu-counts':
1631 iArg += 1;
1632 if iArg >= len(asArgs):
1633 raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
1634
1635 self.acCpus = [];
1636 for s in asArgs[iArg].split(':'):
1637 try: c = int(s);
1638 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
1639 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
1640 self.acCpus.append(c);
1641
1642 elif asArgs[iArg] == '--test-vms':
1643 iArg += 1;
1644 if iArg >= len(asArgs):
1645 raise base.InvalidOption('The "--test-vms" takes colon separated list');
1646
1647 for oTestVm in self.aoTestVms:
1648 oTestVm.fSkip = True;
1649
1650 asTestVMs = asArgs[iArg].split(':');
1651 for s in asTestVMs:
1652 oTestVm = self.findTestVmByName(s);
1653 if oTestVm is None:
1654 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
1655 % (s, self.getAllVmNames(' ')));
1656 oTestVm.fSkip = False;
1657
1658 elif asArgs[iArg] == '--skip-vms':
1659 iArg += 1;
1660 if iArg >= len(asArgs):
1661 raise base.InvalidOption('The "--skip-vms" takes colon separated list');
1662
1663 asTestVMs = asArgs[iArg].split(':');
1664 for s in asTestVMs:
1665 oTestVm = self.findTestVmByName(s);
1666 if oTestVm is None:
1667 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s,));
1668 else:
1669 oTestVm.fSkip = True;
1670
1671 elif asArgs[iArg] == '--snapshot-restore-current':
1672 for oTestVm in self.aoTestVms:
1673 if oTestVm.fSkip is False:
1674 oTestVm.fSnapshotRestoreCurrent = True;
1675 reporter.log('VM "%s" will be restored.' % (oTestVm.sVmName));
1676
1677 elif asArgs[iArg] == '--paravirt-modes':
1678 iArg += 1
1679 if iArg >= len(asArgs):
1680 raise base.InvalidOption('The "--paravirt-modes" takes a colon separated list of modes');
1681
1682 self.asParavirtModes = asArgs[iArg].split(':')
1683 for sPvMode in self.asParavirtModes:
1684 if sPvMode not in g_kasParavirtProviders:
1685 raise base.InvalidOption('The "--paravirt-modes" value "%s" is not valid; valid values are: %s'
1686 % (sPvMode, ', '.join(g_kasParavirtProviders),));
1687 if not self.asParavirtModes:
1688 self.asParavirtModes = None;
1689
1690 # HACK ALERT! Reset the random paravirt selection for members.
1691 for oTestVm in self.aoTestVms:
1692 oTestVm.asParavirtModesSup = oTestVm.asParavirtModesSupOrg;
1693
1694 elif asArgs[iArg] == '--with-nested-hwvirt-only':
1695 for oTestVm in self.aoTestVms:
1696 if oTestVm.fNstHwVirt is False:
1697 oTestVm.fSkip = True;
1698
1699 elif asArgs[iArg] == '--without-nested-hwvirt-only':
1700 for oTestVm in self.aoTestVms:
1701 if oTestVm.fNstHwVirt is True:
1702 oTestVm.fSkip = True;
1703
1704 else:
1705 return iArg;
1706 return iArg + 1;
1707
1708 def getResourceSet(self):
1709 """
1710 Called vbox.TestDriver.getResourceSet and returns a list of paths of resources.
1711 """
1712 asResources = [];
1713 for oTestVm in self.aoTestVms:
1714 if not oTestVm.fSkip:
1715 if isinstance(oTestVm, BaseTestVm): # Temporarily...
1716 asResources.extend(oTestVm.getResourceSet());
1717 else:
1718 if oTestVm.sHd is not None:
1719 asResources.append(oTestVm.sHd);
1720 if oTestVm.sDvdImage is not None:
1721 asResources.append(oTestVm.sDvdImage);
1722 return asResources;
1723
1724 def actionConfig(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
1725 """
1726 For base.TestDriver.actionConfig. Configure the VMs with defaults and
1727 a few tweaks as per arguments.
1728
1729 Returns True if successful.
1730 Returns False if not.
1731 """
1732
1733 for oTestVm in self.aoTestVms:
1734 if oTestVm.fSkip:
1735 continue;
1736 if oTestVm.skipCreatingVm(oTestDrv):
1737 oTestVm.fSkip = True;
1738 continue;
1739
1740 if oTestVm.fSnapshotRestoreCurrent:
1741 # If we want to restore a VM we don't need to create
1742 # the machine anymore -- so just add it to the test VM list.
1743 oVM = oTestDrv.addTestMachine(oTestVm.sVmName);
1744 else:
1745 oVM = oTestVm.createVm(oTestDrv, eNic0AttachType, sDvdImage);
1746 if oVM is None:
1747 return False;
1748
1749 return True;
1750
1751 def _removeUnsupportedVirtModes(self, oTestDrv):
1752 """
1753 Removes unsupported virtualization modes.
1754 """
1755 if 'hwvirt' in self.asVirtModes and not oTestDrv.hasHostHwVirt():
1756 reporter.log('Hardware assisted virtualization is not available on the host, skipping it.');
1757 self.asVirtModes.remove('hwvirt');
1758
1759 if 'hwvirt-np' in self.asVirtModes and not oTestDrv.hasHostNestedPaging():
1760 reporter.log('Nested paging not supported by the host, skipping it.');
1761 self.asVirtModes.remove('hwvirt-np');
1762
1763 if 'raw' in self.asVirtModes and not oTestDrv.hasRawModeSupport():
1764 reporter.log('Raw-mode virtualization is not available in this build (or perhaps for this host), skipping it.');
1765 self.asVirtModes.remove('raw');
1766
1767 return True;
1768
1769 def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=too-many-locals
1770 """
1771 For base.TestDriver.actionExecute. Calls the callback function for
1772 each of the VMs and basic configuration variations (virt-mode and cpu
1773 count).
1774
1775 Returns True if all fnCallback calls returned True, otherwise False.
1776
1777 The callback can return True, False or None. The latter is for when the
1778 test is skipped. (True is for success, False is for failure.)
1779 """
1780
1781 self._removeUnsupportedVirtModes(oTestDrv);
1782 cMaxCpus = oTestDrv.getHostCpuCount();
1783
1784 #
1785 # The test loop.
1786 #
1787 fRc = True;
1788 for oTestVm in self.aoTestVms:
1789 if oTestVm.fSkip and self.fIgnoreSkippedVm:
1790 reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,));
1791 continue;
1792 reporter.testStart(oTestVm.sVmName);
1793 if oTestVm.fSkip:
1794 reporter.testDone(fSkipped = True);
1795 continue;
1796
1797 # Intersect the supported modes and the ones being testing.
1798 asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes];
1799
1800 # Ditto for CPUs.
1801 acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus];
1802
1803 # Ditto for paravirtualization modes, except if not specified we got a less obvious default.
1804 if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0:
1805 asParavirtModes = [sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes];
1806 assert None not in asParavirtModes;
1807 elif oTestDrv.fpApiVer >= 5.0:
1808 asParavirtModes = (oTestVm.asParavirtModesSup[0],);
1809 assert asParavirtModes[0] is not None;
1810 else:
1811 asParavirtModes = (None,);
1812
1813 for cCpus in acCpusSup:
1814 if cCpus == 1:
1815 reporter.testStart('1 cpu');
1816 else:
1817 reporter.testStart('%u cpus' % (cCpus));
1818 if cCpus > cMaxCpus:
1819 reporter.testDone(fSkipped = True);
1820 continue;
1821
1822 cTests = 0;
1823 for sVirtMode in asVirtModesSup:
1824 if sVirtMode == 'raw' and cCpus > 1:
1825 continue;
1826 reporter.testStart('%s' % ( g_dsVirtModeDescs[sVirtMode], ) );
1827 cStartTests = cTests;
1828
1829 for sParavirtMode in asParavirtModes:
1830 if sParavirtMode is not None:
1831 assert oTestDrv.fpApiVer >= 5.0;
1832 reporter.testStart('%s' % ( sParavirtMode, ) );
1833
1834 # Reconfigure the VM.
1835 try:
1836 (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode = sParavirtMode);
1837 except KeyboardInterrupt:
1838 raise;
1839 except:
1840 reporter.errorXcpt(cFrames = 9);
1841 rc2 = False;
1842 if rc2 is True:
1843 # Do the testing.
1844 try:
1845 rc2 = fnCallback(oVM, oTestVm);
1846 except KeyboardInterrupt:
1847 raise;
1848 except:
1849 reporter.errorXcpt(cFrames = 9);
1850 rc2 = False;
1851 if rc2 is False:
1852 reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed');
1853 elif rc2 is False:
1854 reporter.log('getReconfiguredVm failed');
1855 if rc2 is False:
1856 fRc = False;
1857
1858 cTests = cTests + (rc2 is not None);
1859 if sParavirtMode is not None:
1860 reporter.testDone(fSkipped = (rc2 is None));
1861
1862 reporter.testDone(fSkipped = cTests == cStartTests);
1863
1864 reporter.testDone(fSkipped = cTests == 0);
1865
1866 _, cErrors = reporter.testDone();
1867 if cErrors > 0:
1868 fRc = False;
1869 return fRc;
1870
1871 def enumerateTestVms(self, fnCallback):
1872 """
1873 Enumerates all the 'active' VMs.
1874
1875 Returns True if all fnCallback calls returned True.
1876 Returns False if any returned False.
1877 Returns None immediately if fnCallback returned None.
1878 """
1879 fRc = True;
1880 for oTestVm in self.aoTestVms:
1881 if not oTestVm.fSkip:
1882 fRc2 = fnCallback(oTestVm);
1883 if fRc2 is None:
1884 return fRc2;
1885 fRc = fRc and fRc2;
1886 return fRc;
1887
1888
1889
1890class TestVmManager(object):
1891 """
1892 Test VM manager.
1893 """
1894
1895 ## @name VM grouping flags
1896 ## @{
1897 kfGrpSmoke = g_kfGrpSmoke;
1898 kfGrpStandard = g_kfGrpStandard;
1899 kfGrpStdSmoke = g_kfGrpStdSmoke;
1900 kfGrpWithGAs = g_kfGrpWithGAs;
1901 kfGrpNoTxs = g_kfGrpNoTxs;
1902 kfGrpAncient = g_kfGrpAncient;
1903 kfGrpExotic = g_kfGrpExotic;
1904 ## @}
1905
1906 kaTestVMs = (
1907 # Note: The images in the 6.1 folder all have been pre-configured to allow for Guest Additions installation
1908 # (come with build essentials, kernel headers).
1909 # Linux
1910 TestVm('tst-ubuntu-18_04_3-64', kfGrpStdSmoke, sHd = '6.1/ubuntu-18_04_3-amd64-2.vdi',
1911 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True,
1912 asParavirtModesSup = [g_ksParavirtProviderKVM,]),
1913 TestVm('tst-ol-8_1-64-efi', kfGrpStdSmoke, sHd = '6.1/efi/ol-8_1-efi-amd64.vdi',
1914 sKind = 'Oracle_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi',
1915 asParavirtModesSup = [g_ksParavirtProviderKVM,]),
1916 TestVm('tst-ol-6u2-32', kfGrpStdSmoke, sHd = '6.1/ol-6u2-x86.vdi',
1917 sKind = 'Oracle', acCpusSup = range(1, 33), fIoApic = True,
1918 asParavirtModesSup = [g_ksParavirtProviderKVM,]),
1919 TestVm('tst-ubuntu-15_10-64-efi', kfGrpStdSmoke, sHd = '6.1/efi/ubuntu-15_10-efi-amd64-3.vdi',
1920 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi',
1921 asParavirtModesSup = [g_ksParavirtProviderKVM,]),
1922 # Note: Deprecated / buggy; use the one in the 6.1 folder.
1923 #TestVm('tst-ubuntu-15_10-64-efi', kfGrpStdSmoke, sHd = '4.2/efi/ubuntu-15_10-efi-amd64.vdi',
1924 # sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi',
1925 # asParavirtModesSup = [g_ksParavirtProviderKVM,]),
1926 TestVm('tst-rhel5', kfGrpSmoke, sHd = '3.0/tcp/rhel5.vdi',
1927 sKind = 'RedHat', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat'),
1928 TestVm('tst-arch', kfGrpStandard, sHd = '4.2/usb/tst-arch.vdi',
1929 sKind = 'ArchLinux_64', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat'),
1930 # disabled 2019-03-08 klaus - fails all over the place and pollutes the test results
1931 #TestVm('tst-ubuntu-1804-64', kfGrpStdSmoke, sHd = '4.2/ubuntu-1804/t-ubuntu-1804-64.vdi',
1932 # sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True),
1933 TestVm('tst-ol76-64', kfGrpStdSmoke, sHd = '4.2/ol76/t-ol76-64.vdi',
1934 sKind = 'Oracle_64', acCpusSup = range(1, 33), fIoApic = True),
1935 TestVm('tst-ubuntu-20_04-64-amdvi', kfGrpStdSmoke, sHd = '6.1/ubuntu-20_04-64.vdi',
1936 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True,
1937 asParavirtModesSup = [g_ksParavirtProviderKVM,], sNic0AttachType = 'nat', sChipsetType = 'ich9',
1938 sIommuType = 'amd'),
1939 TestVm('tst-ubuntu-20_04-64-vtd', kfGrpStdSmoke, sHd = '6.1/ubuntu-20_04-64.vdi',
1940 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True,
1941 asParavirtModesSup = [g_ksParavirtProviderKVM,], sNic0AttachType = 'nat', sChipsetType = 'ich9',
1942 sIommuType = 'intel'),
1943
1944 # Solaris
1945 TestVm('tst-sol10', kfGrpSmoke, sHd = '3.0/tcp/solaris10.vdi',
1946 sKind = 'Solaris', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged'),
1947 TestVm('tst-sol10-64', kfGrpSmoke, sHd = '3.0/tcp/solaris10.vdi',
1948 sKind = 'Solaris_64', acCpusSup = range(1, 33), sNic0AttachType = 'bridged'),
1949 TestVm('tst-sol11u1', kfGrpSmoke, sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
1950 sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat', fIoApic = True,
1951 sHddControllerType = 'SATA Controller'),
1952 #TestVm('tst-sol11u1-ich9', kfGrpSmoke, sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
1953 # sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat', fIoApic = True,
1954 # sHddControllerType = 'SATA Controller', sChipsetType = 'ich9'),
1955
1956 # NT 3.x
1957 TestVm('tst-nt310', kfGrpAncient, sHd = '5.2/great-old-ones/t-nt310/t-nt310.vdi',
1958 sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
1959 sDvdControllerType = 'BusLogic SCSI Controller'),
1960 TestVm('tst-nt350', kfGrpAncient, sHd = '5.2/great-old-ones/t-nt350/t-nt350.vdi',
1961 sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
1962 sDvdControllerType = 'BusLogic SCSI Controller'),
1963 TestVm('tst-nt351', kfGrpAncient, sHd = '5.2/great-old-ones/t-nt350/t-nt351.vdi',
1964 sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
1965 sDvdControllerType = 'BusLogic SCSI Controller'),
1966
1967 # NT 4
1968 TestVm('tst-nt4sp1', kfGrpStdSmoke, sHd = '4.2/nat/nt4sp1/t-nt4sp1.vdi',
1969 sKind = 'WindowsNT4', acCpusSup = [1], sNic0AttachType = 'nat'),
1970
1971 TestVm('tst-nt4sp6', kfGrpStdSmoke, sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
1972 sKind = 'WindowsNT4', acCpusSup = range(1, 33)),
1973
1974 # W2K
1975 TestVm('tst-2ksp4', kfGrpStdSmoke, sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
1976 sKind = 'Windows2000', acCpusSup = range(1, 33)),
1977
1978 # XP
1979 TestVm('tst-xppro', kfGrpStdSmoke, sHd = '4.2/nat/xppro/t-xppro.vdi',
1980 sKind = 'WindowsXP', acCpusSup = range(1, 33), sNic0AttachType = 'nat'),
1981 TestVm('tst-xpsp2', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxpsp2.vdi',
1982 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1983 TestVm('tst-xpsp2-halaacpi', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
1984 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1985 TestVm('tst-xpsp2-halacpi', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
1986 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1987 TestVm('tst-xpsp2-halapic', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
1988 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1989 TestVm('tst-xpsp2-halmacpi', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
1990 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True),
1991 TestVm('tst-xpsp2-halmps', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
1992 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True),
1993
1994 # W2K3
1995 TestVm('tst-win2k3ent', kfGrpSmoke, sHd = '3.0/tcp/win2k3ent-acpi.vdi',
1996 sKind = 'Windows2003', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged'),
1997
1998 # W7
1999 TestVm('tst-win7', kfGrpStdSmoke, sHd = '6.1/win7-32/t-win7-32.vdi',
2000 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True),
2001 # Note: Deprecated; use the one in the 6.1 folder.
2002 #TestVm('tst-win7', kfGrpStdSmoke, sHd = '4.2/win7-32/t-win7.vdi',
2003 # sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True),
2004
2005 # W8
2006 TestVm('tst-win8-64', kfGrpStdSmoke, sHd = '4.2/win8-64/t-win8-64.vdi',
2007 sKind = 'Windows8_64', acCpusSup = range(1, 33), fIoApic = True),
2008 #TestVm('tst-win8-64-ich9', kfGrpStdSmoke, sHd = '4.2/win8-64/t-win8-64.vdi',
2009 # sKind = 'Windows8_64', acCpusSup = range(1, 33), fIoApic = True, sChipsetType = 'ich9'),
2010
2011 # W10
2012 TestVm('tst-win10-efi', kfGrpStdSmoke, sHd = '4.2/efi/win10-efi-x86.vdi',
2013 sKind = 'Windows10', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi'),
2014 TestVm('tst-win10-64-efi', kfGrpStdSmoke, sHd = '4.2/efi/win10-efi-amd64.vdi',
2015 sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi'),
2016 #TestVm('tst-win10-64-efi-ich9', kfGrpStdSmoke, sHd = '4.2/efi/win10-efi-amd64.vdi',
2017 # sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi', sChipsetType = 'ich9'),
2018
2019 # Nested hardware-virtualization
2020 TestVm('tst-nsthwvirt-ubuntu-64', kfGrpStdSmoke, sHd = '5.3/nat/nsthwvirt-ubuntu64/t-nsthwvirt-ubuntu64.vdi',
2021 sKind = 'Ubuntu_64', acCpusSup = range(1, 2), asVirtModesSup = ['hwvirt-np',], fIoApic = True, fNstHwVirt = True,
2022 sNic0AttachType = 'nat'),
2023
2024 # DOS and Old Windows.
2025 AncientTestVm('tst-dos20', sKind = 'DOS',
2026 sHd = '5.2/great-old-ones/t-dos20/t-dos20.vdi'),
2027 AncientTestVm('tst-dos401-win30me', sKind = 'DOS',
2028 sHd = '5.2/great-old-ones/t-dos401-win30me/t-dos401-win30me.vdi', cMBRamMax = 4),
2029 AncientTestVm('tst-dos401-emm386-win30me', sKind = 'DOS',
2030 sHd = '5.2/great-old-ones/t-dos401-emm386-win30me/t-dos401-emm386-win30me.vdi', cMBRamMax = 4),
2031 AncientTestVm('tst-dos50-win31', sKind = 'DOS',
2032 sHd = '5.2/great-old-ones/t-dos50-win31/t-dos50-win31.vdi'),
2033 AncientTestVm('tst-dos50-emm386-win31', sKind = 'DOS',
2034 sHd = '5.2/great-old-ones/t-dos50-emm386-win31/t-dos50-emm386-win31.vdi'),
2035 AncientTestVm('tst-dos622', sKind = 'DOS',
2036 sHd = '5.2/great-old-ones/t-dos622/t-dos622.vdi'),
2037 AncientTestVm('tst-dos622-emm386', sKind = 'DOS',
2038 sHd = '5.2/great-old-ones/t-dos622-emm386/t-dos622-emm386.vdi'),
2039 AncientTestVm('tst-dos71', sKind = 'DOS',
2040 sHd = '5.2/great-old-ones/t-dos71/t-dos71.vdi'),
2041
2042 #AncientTestVm('tst-dos5-win311a', sKind = 'DOS', sHd = '5.2/great-old-ones/t-dos5-win311a/t-dos5-win311a.vdi'),
2043 );
2044
2045
2046 def __init__(self, sResourcePath):
2047 self.sResourcePath = sResourcePath;
2048
2049 def selectSet(self, fGrouping, sTxsTransport = None, fCheckResources = True):
2050 """
2051 Returns a VM set with the selected VMs.
2052 """
2053 oSet = TestVmSet(oTestVmManager = self);
2054 for oVm in self.kaTestVMs:
2055 if oVm.fGrouping & fGrouping:
2056 if sTxsTransport is None or oVm.sNic0AttachType is None or sTxsTransport == oVm.sNic0AttachType:
2057 if not fCheckResources or not oVm.getMissingResources(self.sResourcePath):
2058 oCopyVm = copy.deepcopy(oVm);
2059 oCopyVm.oSet = oSet;
2060 oSet.aoTestVms.append(oCopyVm);
2061 return oSet;
2062
2063 def getStandardVmSet(self, sTxsTransport):
2064 """
2065 Gets the set of standard test VMs.
2066
2067 This is supposed to do something seriously clever, like searching the
2068 testrsrc tree for usable VMs, but for the moment it's all hard coded. :-)
2069 """
2070 return self.selectSet(self.kfGrpStandard, sTxsTransport)
2071
2072 def getSmokeVmSet(self, sTxsTransport = None):
2073 """Gets a representative set of VMs for smoke testing. """
2074 return self.selectSet(self.kfGrpSmoke, sTxsTransport);
2075
2076 def shutUpPyLint(self):
2077 """ Shut up already! """
2078 return self.sResourcePath;
2079
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