VirtualBox

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

Last change on this file since 96407 was 96407, checked in by vboxsync, 2 years ago

scm copyright and license note update

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