VirtualBox

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

Last change on this file since 79132 was 79132, checked in by vboxsync, 5 years ago

tdAddGuestCtrl.py: More cleanups. Created pathutils.py for dealing with VM specific paths. bugref:9151 bugref:9320

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 89.5 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxtestvms.py 79132 2019-06-13 15:13:12Z vboxsync $
3
4"""
5VirtualBox Test VMs
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2010-2019 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: 79132 $"
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 = [i for i in 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, 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 = 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 isWindows(self):
570 """ Checks if it's a Windows VM. """
571 return self.sGuestOsType == g_ksGuestOsTypeWindows;
572
573 def isOS2(self):
574 """ Checks if it's an OS/2 VM. """
575 return self.sGuestOsType == g_ksGuestOsTypeOS2;
576
577 def isLinux(self):
578 """ Checks if it's an Linux VM. """
579 return self.sGuestOsType == g_ksGuestOsTypeLinux;
580
581 def is64bit(self):
582 """ Checks if it's a 64-bit VM. """
583 return self.sKind.find('_64') >= 0;
584
585 def is64bitRequired(self):
586 """ Check if 64-bit is required or not. """
587 return (self.aInfo[g_iFlags] & g_k64) != 0;
588
589 def isLoggedOntoDesktop(self):
590 """ Checks if the test VM is logging onto a graphical desktop by default. """
591 if self.isWindows():
592 return True;
593 if self.isOS2():
594 return True;
595 if self.sVmName.find('-desktop'):
596 return True;
597 return False;
598
599 def isViaIncompatible(self):
600 """
601 Identifies VMs that doesn't work on VIA.
602
603 Returns True if NOT supported on VIA, False if it IS supported.
604 """
605 # Oracle linux doesn't like VIA in our experience
606 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
607 return True;
608 # OS/2: "The system detected an internal processing error at location
609 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
610 if self.isOS2():
611 return True;
612 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
613 # detected, leading to a STOP 3e(80,0,0,0).
614 if self.aInfo[g_iKind] == 'WindowsNT4':
615 if self.sVmName.find('sp') < 0:
616 return True; # no service pack.
617 if self.sVmName.find('sp0') >= 0 \
618 or self.sVmName.find('sp1') >= 0 \
619 or self.sVmName.find('sp2') >= 0 \
620 or self.sVmName.find('sp3') >= 0:
621 return True;
622 # XP x64 on a physical VIA box hangs exactly like a VM.
623 if self.aInfo[g_iKind] in ['WindowsXP_64', 'Windows2003_64']:
624 return True;
625 # Vista 64 throws BSOD 0x5D (UNSUPPORTED_PROCESSOR)
626 if self.aInfo[g_iKind] in ['WindowsVista_64']:
627 return True;
628 # Solaris 11 hangs on VIA, tested on a physical box (testboxvqc)
629 if self.aInfo[g_iKind] in ['Solaris11_64']:
630 return True;
631 return False;
632
633 def isShanghaiIncompatible(self):
634 """
635 Identifies VMs that doesn't work on Shanghai.
636
637 Returns True if NOT supported on Shanghai, False if it IS supported.
638 """
639 # For now treat it just like VIA, to be adjusted later
640 return self.isViaIncompatible()
641
642 def isP4Incompatible(self):
643 """
644 Identifies VMs that doesn't work on Pentium 4 / Pentium D.
645
646 Returns True if NOT supported on P4, False if it IS supported.
647 """
648 # Stupid 1 kHz timer. Too much for antique CPUs.
649 if self.sVmName.find('rhel5') >= 0:
650 return True;
651 # Due to the boot animation the VM takes forever to boot.
652 if self.aInfo[g_iKind] == 'Windows2000':
653 return True;
654 return False;
655
656 def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv):
657 """
658 Checks if the host OS is affected by older ubuntu installers being very
659 picky about which families of AMD CPUs it would run on.
660
661 The installer checks for family 15, later 16, later 20, and in 11.10
662 they remove the family check for AMD CPUs.
663 """
664 if not oTestDrv.isHostCpuAmd():
665 return False;
666 try:
667 (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0);
668 (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0);
669 except:
670 reporter.logXcpt();
671 return False;
672 if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff:
673 return False;
674
675 uFamily = (uFamilyModel >> 8) & 0xf
676 if uFamily == 0xf:
677 uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf;
678 ## @todo Break this down into which old ubuntu release supports exactly
679 ## which AMD family, if we care.
680 if uFamily <= 15:
681 return False;
682 reporter.log('Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.'
683 % (self.sVmName, uFamily,));
684 return True;
685
686 def getTestUser(self):
687 """
688 Gets the primary test user name.
689 """
690 if self.isWindows():
691 return 'Administrator';
692 return 'vbox';
693
694 def getTestUserPassword(self, sUser = None):
695 """
696 Gets the password for the primary user (or other specified one).
697 """
698 if sUser == 'test':
699 return '';
700 if sUser == 'vboxuser': # Default unattended installation user and password.
701 return 'changeme';
702 return 'password';
703
704 def getCom1RawFile(self, oVM):
705 """
706 Gets the name of the COM1 raw file.
707
708 Returns string, None on failure or if not active.
709
710 Note! Do not access __sCom1RawFile directly as it will not be set unless the
711 'config' action was executed in the same run.
712 """
713 if self.fCom1RawFile:
714 # Retrieve it from the IMachine object and cache the result if needed:
715 if self.__sCom1RawFile is None:
716 try:
717 oPort = oVM.machine.getSerialPort(0);
718 except:
719 reporter.errorXcpt('failed to get serial port #0');
720 else:
721 try:
722 self.__sCom1RawFile = oPort.path;
723 except:
724 reporter.errorXcpt('failed to get the "path" property on serial port #0');
725 return self.__sCom1RawFile;
726
727 reporter.error('getCom1RawFile called when fCom1RawFile is False');
728 return None;
729
730 def getIGuestOSType(self, oVBoxWrapped):
731 """
732 Gets the IGuestOSType object corresponding to self.sKind.
733
734 Returns object on success, None on failure (logged as error).
735 """
736 try:
737 return oVBoxWrapped.o.getGuestOSType(self.sKind);
738 except:
739 reporter.errorXcpt('sVmName=%s sKind=%s' % (self.sVmName, self.sKind,));
740 return None;
741
742 def getRecommendedHddSize(self, oVBoxWrapped):
743 """
744 Gets the recommended HDD size from the IGuestOSType matching self.sKind.
745
746 Returns size in bytes on success, -1 on failure.
747 """
748 if self.__cbHdd < 0:
749 oGuestOSType = self.getIGuestOSType(oVBoxWrapped);
750 if oGuestOSType:
751 try:
752 self.__cbHdd = oGuestOSType.recommendedHDD;
753 except:
754 reporter.errorXcpt();
755 return -1;
756 return self.__cbHdd;
757
758 def getHddAddress(self, oVM, oVBoxWrapped):
759 """
760 Gets the HDD attachment address.
761
762 Returns (sController, iPort, iDevice) on success; (None, None, None) on failure.
763
764 Note! Do not access the cached value directly!
765 """
766 # Cached already?
767 if self.__tHddCtrlPortDev[0] is not None:
768 return self.__tHddCtrlPortDev;
769
770 # First look for HDs attached to the VM:
771 try:
772 aoAttachments = oVBoxWrapped.oVBoxMgr.getArray(oVM, 'mediumAttachments')
773 except:
774 reporter.errorXcpt();
775 else:
776 for oAtt in aoAttachments:
777 try:
778 sCtrl = oAtt.controller
779 iPort = oAtt.port;
780 iDev = oAtt.device;
781 eType = oAtt.type;
782 except:
783 reporter.errorXcpt();
784 return self.__tHddCtrlPortDev;
785 if eType == vboxcon.DeviceType_HardDisk:
786 self.__tHddCtrlPortDev = (sCtrl, iPort, iDev);
787 reporter.log2('getHddAddress: %s, %s, %s' % self.__tHddCtrlPortDev);
788 return self.__tHddCtrlPortDev;
789
790 # Then consult IGuestOSType:
791 oGuestOSType = self.getIGuestOSType(oVBoxWrapped);
792 if oGuestOSType:
793 try:
794 eCtrl = oGuestOSType.recommendedHDStorageController;
795 eBus = oGuestOSType.RecommendedHDStorageBus;
796 except:
797 reporter.errorXcpt();
798 else:
799 self.__tHddCtrlPortDev = (self._storageCtrlAndBusToName(oVM, eCtrl, eBus), 0, 0); # ASSUMES port 0, device 0.
800 reporter.log2('getHddAddress: %s, %s, %s [IGuestOSType]' % self.__tHddCtrlPortDev);
801 return self.__tHddCtrlPortDev;
802
803 def getDvdAddress(self, oVM, oVBoxWrapped):
804 """
805 Gets the DVD attachment address.
806
807 Returns (sController, iPort, iDevice) on success; (None, None, None) on failure.
808
809 Note! Do not access the cached value directly!
810 """
811 # Cached already?
812 if self.__tDvdCtrlPortDev[0] is not None:
813 return self.__tDvdCtrlPortDev;
814
815 # First look for DVD attached to the VM:
816 try:
817 aoAttachments = oVBoxWrapped.oVBoxMgr.getArray(oVM, 'mediumAttachments')
818 except:
819 reporter.errorXcpt();
820 else:
821 for oAtt in aoAttachments:
822 try:
823 sCtrl = oAtt.controller
824 iPort = oAtt.port;
825 iDev = oAtt.device;
826 eType = oAtt.type;
827 except:
828 reporter.errorXcpt();
829 return self.__tDvdCtrlPortDev;
830 if eType == vboxcon.DeviceType_DVD:
831 self.__tDvdCtrlPortDev = (sCtrl, iPort, iDev);
832 reporter.log2('getDvdAddress: %s, %s, %s' % self.__tDvdCtrlPortDev);
833 return self.__tDvdCtrlPortDev;
834
835 # Then consult IGuestOSType:
836 oGuestOSType = self.getIGuestOSType(oVBoxWrapped);
837 if oGuestOSType:
838 try:
839 eCtrl = oGuestOSType.recommendedDVDStorageController;
840 eBus = oGuestOSType.RecommendedDVDStorageBus;
841 except:
842 reporter.errorXcpt();
843 else:
844 self.__tDvdCtrlPortDev = (self._storageCtrlAndBusToName(oVM, eCtrl, eBus), 1, 0); # ASSUMES port 1, device 0.
845 reporter.log2('getDvdAddress: %s, %s, %s [IGuestOSType]' % self.__tDvdCtrlPortDev);
846 return self.__tDvdCtrlPortDev;
847
848 def recreateRecommendedHdd(self, oVM, oTestDrv, sHddPath = None):
849 """
850 Detaches and delete any current hard disk and then ensures that a new
851 one with the recommended size is created and attached to the recommended
852 controller/port/device.
853
854 Returns True/False (errors logged).
855 """
856 # Generate a name if none was given:
857 if not sHddPath:
858 try:
859 sHddPath = oVM.settingsFilePath;
860 except:
861 return reporter.errorXcpt();
862 sHddPath = os.path.join(os.path.dirname(sHddPath), '%s-%s.vdi' % (self.sVmName, uuid.uuid4(),));
863
864 fRc = False;
865
866 # Get the hard disk specs first:
867 cbHdd = self.getRecommendedHddSize(oTestDrv.oVBox);
868 tHddAddress = self.getHddAddress(oVM, oTestDrv.oVBox);
869 assert len(tHddAddress) == 3;
870 if tHddAddress[0] and cbHdd > 0:
871 # Open an session so we can make changes:
872 oSession = oTestDrv.openSession(oVM);
873 if oSession is not None:
874 # Detach the old disk (this will succeed with oOldHd set to None the first time around).
875 (fRc, oOldHd) = oSession.detachHd(tHddAddress[0], tHddAddress[1], tHddAddress[2]);
876 if fRc:
877 # Create a new disk and attach it.
878 fRc = oSession.createAndAttachHd(sHddPath,
879 cb = cbHdd,
880 sController = tHddAddress[0],
881 iPort = tHddAddress[1],
882 iDevice = tHddAddress[2],
883 fImmutable = False);
884 if fRc:
885 # Save the changes.
886 fRc = oSession.saveSettings();
887
888 # Delete the old HD:
889 if fRc and oOldHd is not None:
890 fRc = fRc and oTestDrv.oVBox.deleteHdByMedium(oOldHd);
891 fRc = fRc and oSession.saveSettings(); # Necessary for media reg??
892 else:
893 oSession.discardSettings();
894 fRc = oSession.close() and fRc;
895 return fRc;
896
897 def pathJoinEx(self, sBase, *asAppend):
898 """ See common.pathutils.joinEx(). """
899 return pathutils.joinEx(self.isWindows() or self.isOS2(), sBase, *asAppend);
900
901
902
903## @todo Inherit from BaseTestVm
904class TestVm(object):
905 """
906 A Test VM - name + VDI/whatever.
907
908 This is just a data object.
909 """
910
911 def __init__(self, # pylint: disable=too-many-arguments
912 sVmName, # type: str
913 fGrouping = 0, # type: int
914 oSet = None, # type: TestVmSet
915 sHd = None, # type: str
916 sKind = None, # type: str
917 acCpusSup = None, # type: List[int]
918 asVirtModesSup = None, # type: List[str]
919 fIoApic = None, # type: bool
920 fNstHwVirt = False, # type: bool
921 fPae = None, # type: bool
922 sNic0AttachType = None, # type: str
923 sFloppy = None, # type: str
924 fVmmDevTestingPart = None, # type: bool
925 fVmmDevTestingMmio = False, # type: bool
926 asParavirtModesSup = None, # type: List[str]
927 fRandomPvPMode = False, # type: bool
928 sFirmwareType = 'bios', # type: str
929 sChipsetType = 'piix3', # type: str
930 sHddControllerType = 'IDE Controller', # type: str
931 sDvdControllerType = 'IDE Controller' # type: str
932 ):
933 self.oSet = oSet;
934 self.sVmName = sVmName;
935 self.fGrouping = fGrouping;
936 self.sHd = sHd; # Relative to the testrsrc root.
937 self.acCpusSup = acCpusSup;
938 self.asVirtModesSup = asVirtModesSup;
939 self.asParavirtModesSup = asParavirtModesSup;
940 self.asParavirtModesSupOrg = asParavirtModesSup; # HACK ALERT! Trick to make the 'effing random mess not get in the
941 # way of actively selecting virtualization modes.
942 self.sKind = sKind;
943 self.sGuestOsType = None;
944 self.sDvdImage = None; # Relative to the testrsrc root.
945 self.sDvdControllerType = sDvdControllerType;
946 self.fIoApic = fIoApic;
947 self.fNstHwVirt = fNstHwVirt;
948 self.fPae = fPae;
949 self.sNic0AttachType = sNic0AttachType;
950 self.sHddControllerType = sHddControllerType;
951 self.sFloppy = sFloppy; # Relative to the testrsrc root, except when it isn't...
952 self.fVmmDevTestingPart = fVmmDevTestingPart;
953 self.fVmmDevTestingMmio = fVmmDevTestingMmio;
954 self.sFirmwareType = sFirmwareType;
955 self.sChipsetType = sChipsetType;
956 self.fCom1RawFile = False;
957
958 self.fSnapshotRestoreCurrent = False; # Whether to restore execution on the current snapshot.
959 self.fSkip = False; # All VMs are included in the configured set by default.
960 self.aInfo = None;
961 self.sCom1RawFile = None; # Set by createVmInner and getReconfiguredVm if fCom1RawFile is set.
962 self._guessStuff(fRandomPvPMode);
963
964 def _mkCanonicalGuestOSType(self, sType):
965 """
966 Convert guest OS type into constant representation.
967 Raise exception if specified @param sType is unknown.
968 """
969 if sType.lower().startswith('darwin'):
970 return g_ksGuestOsTypeDarwin
971 if sType.lower().startswith('bsd'):
972 return g_ksGuestOsTypeFreeBSD
973 if sType.lower().startswith('dos'):
974 return g_ksGuestOsTypeDOS
975 if sType.lower().startswith('linux'):
976 return g_ksGuestOsTypeLinux
977 if sType.lower().startswith('os2'):
978 return g_ksGuestOsTypeOS2
979 if sType.lower().startswith('solaris'):
980 return g_ksGuestOsTypeSolaris
981 if sType.lower().startswith('windows'):
982 return g_ksGuestOsTypeWindows
983 raise base.GenError(sWhat="unknown guest OS kind: %s" % str(sType))
984
985 def _guessStuff(self, fRandomPvPMode):
986 """
987 Used by the constructor to guess stuff.
988 """
989
990 sNm = self.sVmName.lower().strip();
991 asSplit = sNm.replace('-', ' ').split(' ');
992
993 if self.sKind is None:
994 # From name.
995 for aInfo in g_aaNameToDetails:
996 if _intersects(asSplit, aInfo[g_iRegEx]):
997 self.aInfo = aInfo;
998 self.sGuestOsType = self._mkCanonicalGuestOSType(aInfo[g_iGuestOsType])
999 self.sKind = aInfo[g_iKind];
1000 break;
1001 if self.sKind is None:
1002 reporter.fatal('The OS of test VM "%s" cannot be guessed' % (self.sVmName,));
1003
1004 # Check for 64-bit, if required and supported.
1005 if (self.aInfo[g_iFlags] & g_kiArchMask) == g_k32_64 and _intersects(asSplit, ['64', 'amd64']):
1006 self.sKind = self.sKind + '_64';
1007 else:
1008 # Lookup the kind.
1009 for aInfo in g_aaNameToDetails:
1010 if self.sKind == aInfo[g_iKind]:
1011 self.aInfo = aInfo;
1012 break;
1013 if self.aInfo is None:
1014 reporter.fatal('The OS of test VM "%s" with sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
1015
1016 # Translate sKind into sGuest OS Type.
1017 if self.sGuestOsType is None:
1018 if self.aInfo is not None:
1019 self.sGuestOsType = self._mkCanonicalGuestOSType(self.aInfo[g_iGuestOsType])
1020 elif self.sKind.find("Windows") >= 0:
1021 self.sGuestOsType = g_ksGuestOsTypeWindows
1022 elif self.sKind.find("Linux") >= 0:
1023 self.sGuestOsType = g_ksGuestOsTypeLinux;
1024 elif self.sKind.find("Solaris") >= 0:
1025 self.sGuestOsType = g_ksGuestOsTypeSolaris;
1026 elif self.sKind.find("DOS") >= 0:
1027 self.sGuestOsType = g_ksGuestOsTypeDOS;
1028 else:
1029 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
1030
1031 # Restrict modes and such depending on the OS.
1032 if self.asVirtModesSup is None:
1033 self.asVirtModesSup = list(g_asVirtModes);
1034 if self.sGuestOsType in (g_ksGuestOsTypeOS2, g_ksGuestOsTypeDarwin) \
1035 or self.sKind.find('_64') > 0 \
1036 or (self.aInfo is not None and (self.aInfo[g_iFlags] & g_kiNoRaw)):
1037 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
1038 # TEMPORARY HACK - START
1039 sHostName = os.environ.get("COMPUTERNAME", None);
1040 if sHostName: sHostName = sHostName.lower();
1041 else: sHostName = socket.getfqdn(); # Horribly slow on windows without IPv6 DNS/whatever.
1042 if sHostName.startswith('testboxpile1'):
1043 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
1044 # TEMPORARY HACK - END
1045
1046 # Restrict the CPU count depending on the OS and/or percieved SMP readiness.
1047 if self.acCpusSup is None:
1048 if _intersects(asSplit, ['uni']):
1049 self.acCpusSup = [1];
1050 elif self.aInfo is not None:
1051 self.acCpusSup = [i for i in range(self.aInfo[g_iMinCpu], self.aInfo[g_iMaxCpu]) ];
1052 else:
1053 self.acCpusSup = [1];
1054
1055 # Figure relevant PV modes based on the OS.
1056 if self.asParavirtModesSup is None:
1057 self.asParavirtModesSup = g_kdaParavirtProvidersSupported[self.sGuestOsType];
1058 ## @todo Remove this hack as soon as we've got around to explictly configure test variations
1059 ## on the server side. Client side random is interesting but not the best option.
1060 self.asParavirtModesSupOrg = self.asParavirtModesSup;
1061 if fRandomPvPMode:
1062 random.seed();
1063 self.asParavirtModesSup = (random.choice(self.asParavirtModesSup),);
1064
1065 return True;
1066
1067 def getNonCanonicalGuestOsType(self):
1068 """
1069 Gets the non-canonical OS type (self.sGuestOsType is canonical).
1070 """
1071 return self.aInfo[g_iGuestOsType];
1072
1073 def getMissingResources(self, sTestRsrc):
1074 """
1075 Returns a list of missing resources (paths, stuff) that the VM needs.
1076 """
1077 asRet = [];
1078 for sPath in [ self.sHd, self.sDvdImage, self.sFloppy]:
1079 if sPath is not None:
1080 if not os.path.isabs(sPath):
1081 sPath = os.path.join(sTestRsrc, sPath);
1082 if not os.path.exists(sPath):
1083 asRet.append(sPath);
1084 return asRet;
1085
1086 def skipCreatingVm(self, oTestDrv):
1087 """
1088 Called before VM creation to determine whether the VM should be skipped
1089 due to host incompatibility or something along those lines.
1090
1091 returns True if it should be skipped, False if not.
1092 """
1093 if self.fNstHwVirt and not oTestDrv.isHostCpuAmd():
1094 reporter.log('Ignoring VM %s (Nested hardware-virtualization only supported on AMD CPUs).' % (self.sVmName,));
1095 return True;
1096 return False;
1097
1098 def createVm(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
1099 """
1100 Creates the VM with defaults and the few tweaks as per the arguments.
1101
1102 Returns same as vbox.TestDriver.createTestVM.
1103 """
1104 if sDvdImage is not None:
1105 sMyDvdImage = sDvdImage;
1106 else:
1107 sMyDvdImage = self.sDvdImage;
1108
1109 if eNic0AttachType is not None:
1110 eMyNic0AttachType = eNic0AttachType;
1111 elif self.sNic0AttachType is None:
1112 eMyNic0AttachType = None;
1113 elif self.sNic0AttachType == 'nat':
1114 eMyNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
1115 elif self.sNic0AttachType == 'bridged':
1116 eMyNic0AttachType = vboxcon.NetworkAttachmentType_Bridged;
1117 else:
1118 assert False, self.sNic0AttachType;
1119
1120 return self.createVmInner(oTestDrv, eMyNic0AttachType, sMyDvdImage);
1121
1122 def _generateRawPortFilename(self, oTestDrv, sInfix, sSuffix):
1123 """ Generates a raw port filename. """
1124 random.seed();
1125 sRandom = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10));
1126 return os.path.join(oTestDrv.sScratchPath, self.sVmName + sInfix + sRandom + sSuffix);
1127
1128 def createVmInner(self, oTestDrv, eNic0AttachType, sDvdImage):
1129 """
1130 Same as createVm but parameters resolved.
1131
1132 Returns same as vbox.TestDriver.createTestVM.
1133 """
1134 reporter.log2('');
1135 reporter.log2('Calling createTestVM on %s...' % (self.sVmName,))
1136 if self.fCom1RawFile:
1137 self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
1138 return oTestDrv.createTestVM(self.sVmName,
1139 1, # iGroup
1140 sHd = self.sHd,
1141 sKind = self.sKind,
1142 fIoApic = self.fIoApic,
1143 fNstHwVirt = self.fNstHwVirt,
1144 fPae = self.fPae,
1145 eNic0AttachType = eNic0AttachType,
1146 sDvdImage = sDvdImage,
1147 sDvdControllerType = self.sDvdControllerType,
1148 sHddControllerType = self.sHddControllerType,
1149 sFloppy = self.sFloppy,
1150 fVmmDevTestingPart = self.fVmmDevTestingPart,
1151 fVmmDevTestingMmio = self.fVmmDevTestingMmio,
1152 sFirmwareType = self.sFirmwareType,
1153 sChipsetType = self.sChipsetType,
1154 sCom1RawFile = self.sCom1RawFile if self.fCom1RawFile else None
1155 );
1156
1157 def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None):
1158 """
1159 actionExecute worker that finds and reconfigure a test VM.
1160
1161 Returns (fRc, oVM) where fRc is True, None or False and oVM is a
1162 VBox VM object that is only present when rc is True.
1163 """
1164
1165 fRc = False;
1166 oVM = oTestDrv.getVmByName(self.sVmName);
1167 if oVM is not None:
1168 if self.fSnapshotRestoreCurrent is True:
1169 fRc = True;
1170 else:
1171 fHostSupports64bit = oTestDrv.hasHostLongMode();
1172 if self.is64bitRequired() and not fHostSupports64bit:
1173 fRc = None; # Skip the test.
1174 elif self.isViaIncompatible() and oTestDrv.isHostCpuVia():
1175 fRc = None; # Skip the test.
1176 elif self.isShanghaiIncompatible() and oTestDrv.isHostCpuShanghai():
1177 fRc = None; # Skip the test.
1178 elif self.isP4Incompatible() and oTestDrv.isHostCpuP4():
1179 fRc = None; # Skip the test.
1180 else:
1181 oSession = oTestDrv.openSession(oVM);
1182 if oSession is not None:
1183 fRc = oSession.enableVirtEx(sVirtMode != 'raw');
1184 fRc = fRc and oSession.enableNestedPaging(sVirtMode == 'hwvirt-np');
1185 fRc = fRc and oSession.setCpuCount(cCpus);
1186 if cCpus > 1:
1187 fRc = fRc and oSession.enableIoApic(True);
1188
1189 if sParavirtMode is not None and oSession.fpApiVer >= 5.0:
1190 adParavirtProviders = {
1191 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None,
1192 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default,
1193 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy,
1194 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal,
1195 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV,
1196 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM,
1197 };
1198 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]);
1199
1200 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw');
1201 fRc = fRc and oSession.enableLongMode(fCfg64Bit);
1202 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh.
1203 oOsType = oSession.getOsType();
1204 if oOsType is not None:
1205 if oOsType.is64Bit and sVirtMode == 'raw':
1206 assert(oOsType.id[-3:] == '_64');
1207 fRc = fRc and oSession.setOsType(oOsType.id[:-3]);
1208 elif not oOsType.is64Bit and sVirtMode != 'raw':
1209 fRc = fRc and oSession.setOsType(oOsType.id + '_64');
1210
1211 # New serial raw file.
1212 if fRc and self.fCom1RawFile:
1213 self.sCom1RawFile = self._generateRawPortFilename(oTestDrv, '-com1-', '.out');
1214 utils.noxcptDeleteFile(self.sCom1RawFile);
1215 fRc = oSession.setupSerialToRawFile(0, self.sCom1RawFile);
1216
1217 # Make life simpler for child classes.
1218 if fRc:
1219 fRc = self._childVmReconfig(oTestDrv, oVM, oSession);
1220
1221 fRc = fRc and oSession.saveSettings();
1222 if not oSession.close():
1223 fRc = False;
1224 if fRc is True:
1225 return (True, oVM);
1226 return (fRc, None);
1227
1228 def _childVmReconfig(self, oTestDrv, oVM, oSession):
1229 """ Hook into getReconfiguredVm() for children. """
1230 _ = oTestDrv; _ = oVM; _ = oSession;
1231 return True;
1232
1233 def isWindows(self):
1234 """ Checks if it's a Windows VM. """
1235 return self.sGuestOsType == g_ksGuestOsTypeWindows;
1236
1237 def isOS2(self):
1238 """ Checks if it's an OS/2 VM. """
1239 return self.sGuestOsType == g_ksGuestOsTypeOS2;
1240
1241 def isLinux(self):
1242 """ Checks if it's an Linux VM. """
1243 return self.sGuestOsType == g_ksGuestOsTypeLinux;
1244
1245 def is64bit(self):
1246 """ Checks if it's a 64-bit VM. """
1247 return self.sKind.find('_64') >= 0;
1248
1249 def is64bitRequired(self):
1250 """ Check if 64-bit is required or not. """
1251 return (self.aInfo[g_iFlags] & g_k64) != 0;
1252
1253 def isLoggedOntoDesktop(self):
1254 """ Checks if the test VM is logging onto a graphical desktop by default. """
1255 if self.isWindows():
1256 return True;
1257 if self.isOS2():
1258 return True;
1259 if self.sVmName.find('-desktop'):
1260 return True;
1261 return False;
1262
1263 def isViaIncompatible(self):
1264 """
1265 Identifies VMs that doesn't work on VIA.
1266
1267 Returns True if NOT supported on VIA, False if it IS supported.
1268 """
1269 # Oracle linux doesn't like VIA in our experience
1270 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
1271 return True;
1272 # OS/2: "The system detected an internal processing error at location
1273 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
1274 if self.isOS2():
1275 return True;
1276 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
1277 # detected, leading to a STOP 3e(80,0,0,0).
1278 if self.aInfo[g_iKind] == 'WindowsNT4':
1279 if self.sVmName.find('sp') < 0:
1280 return True; # no service pack.
1281 if self.sVmName.find('sp0') >= 0 \
1282 or self.sVmName.find('sp1') >= 0 \
1283 or self.sVmName.find('sp2') >= 0 \
1284 or self.sVmName.find('sp3') >= 0:
1285 return True;
1286 # XP x64 on a physical VIA box hangs exactly like a VM.
1287 if self.aInfo[g_iKind] in ['WindowsXP_64', 'Windows2003_64']:
1288 return True;
1289 # Vista 64 throws BSOD 0x5D (UNSUPPORTED_PROCESSOR)
1290 if self.aInfo[g_iKind] in ['WindowsVista_64']:
1291 return True;
1292 # Solaris 11 hangs on VIA, tested on a physical box (testboxvqc)
1293 if self.aInfo[g_iKind] in ['Solaris11_64']:
1294 return True;
1295 return False;
1296
1297 def isShanghaiIncompatible(self):
1298 """
1299 Identifies VMs that doesn't work on Shanghai.
1300
1301 Returns True if NOT supported on Shanghai, False if it IS supported.
1302 """
1303 # For now treat it just like VIA, to be adjusted later
1304 return self.isViaIncompatible()
1305
1306 def isP4Incompatible(self):
1307 """
1308 Identifies VMs that doesn't work on Pentium 4 / Pentium D.
1309
1310 Returns True if NOT supported on P4, False if it IS supported.
1311 """
1312 # Stupid 1 kHz timer. Too much for antique CPUs.
1313 if self.sVmName.find('rhel5') >= 0:
1314 return True;
1315 # Due to the boot animation the VM takes forever to boot.
1316 if self.aInfo[g_iKind] == 'Windows2000':
1317 return True;
1318 return False;
1319
1320 def isHostCpuAffectedByUbuntuNewAmdBug(self, oTestDrv):
1321 """
1322 Checks if the host OS is affected by older ubuntu installers being very
1323 picky about which families of AMD CPUs it would run on.
1324
1325 The installer checks for family 15, later 16, later 20, and in 11.10
1326 they remove the family check for AMD CPUs.
1327 """
1328 if not oTestDrv.isHostCpuAmd():
1329 return False;
1330 try:
1331 (uMaxExt, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000000, 0);
1332 (uFamilyModel, _, _, _) = oTestDrv.oVBox.host.getProcessorCPUIDLeaf(0, 0x80000001, 0);
1333 except:
1334 reporter.logXcpt();
1335 return False;
1336 if uMaxExt < 0x80000001 or uMaxExt > 0x8000ffff:
1337 return False;
1338
1339 uFamily = (uFamilyModel >> 8) & 0xf
1340 if uFamily == 0xf:
1341 uFamily = ((uFamilyModel >> 20) & 0x7f) + 0xf;
1342 ## @todo Break this down into which old ubuntu release supports exactly
1343 ## which AMD family, if we care.
1344 if uFamily <= 15:
1345 return False;
1346 reporter.log('Skipping "%s" because host CPU is a family %u AMD, which may cause trouble for the guest OS installer.'
1347 % (self.sVmName, uFamily,));
1348 return True;
1349
1350 def getTestUser(self):
1351 """
1352 Gets the primary test user name.
1353 """
1354 if self.isWindows():
1355 return 'Administrator';
1356 return 'vbox';
1357
1358 def getTestUserPassword(self, sUser = None):
1359 """
1360 Gets the password for the primary user (or other specified one).
1361 """
1362 if sUser == 'test':
1363 return '';
1364 if sUser == 'vboxuser': # Default unattended installation user and password.
1365 return 'changeme';
1366 return 'password';
1367
1368 def pathJoinEx(self, sBase, *asAppend):
1369 """ See common.pathutils.joinEx(). """
1370 return pathutils.joinEx(self.isWindows() or self.isOS2(), sBase, *asAppend);
1371
1372
1373
1374class BootSectorTestVm(TestVm):
1375 """
1376 A Boot Sector Test VM.
1377 """
1378
1379 def __init__(self, oSet, sVmName, sFloppy = None, asVirtModesSup = None, f64BitRequired = False):
1380 self.f64BitRequired = f64BitRequired;
1381 if asVirtModesSup is None:
1382 asVirtModesSup = list(g_asVirtModes);
1383 TestVm.__init__(self, sVmName,
1384 oSet = oSet,
1385 acCpusSup = [1,],
1386 sFloppy = sFloppy,
1387 asVirtModesSup = asVirtModesSup,
1388 fPae = True,
1389 fIoApic = True,
1390 fVmmDevTestingPart = True,
1391 fVmmDevTestingMmio = True,
1392 );
1393
1394 def is64bitRequired(self):
1395 return self.f64BitRequired;
1396
1397
1398class AncientTestVm(TestVm):
1399 """
1400 A ancient Test VM, using the serial port for communicating results.
1401
1402 We're looking for 'PASSED' and 'FAILED' lines in the COM1 output.
1403 """
1404
1405
1406 def __init__(self, # pylint: disable=too-many-arguments
1407 sVmName, # type: str
1408 fGrouping = g_kfGrpAncient | g_kfGrpNoTxs, # type: int
1409 sHd = None, # type: str
1410 sKind = None, # type: str
1411 acCpusSup = None, # type: List[int]
1412 asVirtModesSup = None, # type: List[str]
1413 sNic0AttachType = None, # type: str
1414 sFloppy = None, # type: str
1415 sFirmwareType = 'bios', # type: str
1416 sChipsetType = 'piix3', # type: str
1417 sHddControllerName = 'IDE Controller', # type: str
1418 sDvdControllerName = 'IDE Controller', # type: str
1419 cMBRamMax = None, # type: int
1420 ):
1421 TestVm.__init__(self,
1422 sVmName,
1423 fGrouping = fGrouping,
1424 sHd = sHd,
1425 sKind = sKind,
1426 acCpusSup = [1] if acCpusSup is None else acCpusSup,
1427 asVirtModesSup = asVirtModesSup,
1428 sNic0AttachType = sNic0AttachType,
1429 sFloppy = sFloppy,
1430 sFirmwareType = sFirmwareType,
1431 sChipsetType = sChipsetType,
1432 sHddControllerType = sHddControllerName,
1433 sDvdControllerType = sDvdControllerName,
1434 asParavirtModesSup = (g_ksParavirtProviderNone,)
1435 );
1436 self.fCom1RawFile = True;
1437 self.cMBRamMax= cMBRamMax;
1438
1439
1440 def _childVmReconfig(self, oTestDrv, oVM, oSession):
1441 _ = oVM; _ = oTestDrv;
1442 fRc = True;
1443
1444 # DOS 4.01 doesn't like the default 32MB of memory.
1445 if fRc and self.cMBRamMax is not None:
1446 try:
1447 cMBRam = oSession.o.machine.memorySize;
1448 except:
1449 cMBRam = self.cMBRamMax + 4;
1450 if self.cMBRamMax < cMBRam:
1451 fRc = oSession.setRamSize(self.cMBRamMax);
1452
1453 return fRc;
1454
1455
1456class TestVmSet(object):
1457 """
1458 A set of Test VMs.
1459 """
1460
1461 def __init__(self, oTestVmManager = None, acCpus = None, asVirtModes = None, fIgnoreSkippedVm = False):
1462 self.oTestVmManager = oTestVmManager;
1463 if acCpus is None:
1464 acCpus = [1, 2];
1465 self.acCpusDef = acCpus;
1466 self.acCpus = acCpus;
1467 if asVirtModes is None:
1468 asVirtModes = list(g_asVirtModes);
1469 self.asVirtModesDef = asVirtModes;
1470 self.asVirtModes = asVirtModes;
1471 self.aoTestVms = [] # type: list(BaseTestVm)
1472 self.fIgnoreSkippedVm = fIgnoreSkippedVm;
1473 self.asParavirtModes = None; ##< If None, use the first PV mode of the test VM, otherwise all modes in this list.
1474
1475 def findTestVmByName(self, sVmName):
1476 """
1477 Returns the TestVm object with the given name.
1478 Returns None if not found.
1479 """
1480
1481 # The 'tst-' prefix is optional.
1482 sAltName = sVmName if sVmName.startswith('tst-') else 'tst-' + sVmName;
1483
1484 for oTestVm in self.aoTestVms:
1485 if oTestVm.sVmName == sVmName or oTestVm.sVmName == sAltName:
1486 return oTestVm;
1487 return None;
1488
1489 def getAllVmNames(self, sSep = ':'):
1490 """
1491 Returns names of all the test VMs in the set separated by
1492 sSep (defaults to ':').
1493 """
1494 sVmNames = '';
1495 for oTestVm in self.aoTestVms:
1496 sName = oTestVm.sVmName;
1497 if sName.startswith('tst-'):
1498 sName = sName[4:];
1499 if sVmNames == '':
1500 sVmNames = sName;
1501 else:
1502 sVmNames = sVmNames + sSep + sName;
1503 return sVmNames;
1504
1505 def showUsage(self):
1506 """
1507 Invoked by vbox.TestDriver.
1508 """
1509 reporter.log('');
1510 reporter.log('Test VM selection and general config options:');
1511 reporter.log(' --virt-modes <m1[:m2[:...]]>');
1512 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
1513 reporter.log(' --skip-virt-modes <m1[:m2[:...]]>');
1514 reporter.log(' Use this to avoid hwvirt or hwvirt-np when not supported by the host');
1515 reporter.log(' since we cannot detect it using the main API. Use after --virt-modes.');
1516 reporter.log(' --cpu-counts <c1[:c2[:...]]>');
1517 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
1518 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
1519 reporter.log(' Test the specified VMs in the given order. Use this to change');
1520 reporter.log(' the execution order or limit the choice of VMs');
1521 reporter.log(' Default: %s (all)' % (self.getAllVmNames(),));
1522 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
1523 reporter.log(' Skip the specified VMs when testing.');
1524 reporter.log(' --snapshot-restore-current');
1525 reporter.log(' Restores the current snapshot and resumes execution.');
1526 reporter.log(' --paravirt-modes <pv1[:pv2[:...]]>');
1527 reporter.log(' Set of paravirtualized providers (modes) to tests. Intersected with what the test VM supports.');
1528 reporter.log(' Default is the first PV mode the test VMs support, generally same as "legacy".');
1529 reporter.log(' --with-nested-hwvirt-only');
1530 reporter.log(' Test VMs using nested hardware-virtualization only.');
1531 reporter.log(' --without-nested-hwvirt-only');
1532 reporter.log(' Test VMs not using nested hardware-virtualization only.');
1533 ## @todo Add more options for controlling individual VMs.
1534 return True;
1535
1536 def parseOption(self, asArgs, iArg):
1537 """
1538 Parses the set test vm set options (--test-vms and --skip-vms), modifying the set
1539 Invoked by the testdriver method with the same name.
1540
1541 Keyword arguments:
1542 asArgs -- The argument vector.
1543 iArg -- The index of the current argument.
1544
1545 Returns iArg if the option was not recognized and the caller should handle it.
1546 Returns the index of the next argument when something is consumed.
1547
1548 In the event of a syntax error, a InvalidOption or QuietInvalidOption
1549 is thrown.
1550 """
1551
1552 if asArgs[iArg] == '--virt-modes':
1553 iArg += 1;
1554 if iArg >= len(asArgs):
1555 raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
1556
1557 self.asVirtModes = asArgs[iArg].split(':');
1558 for s in self.asVirtModes:
1559 if s not in self.asVirtModesDef:
1560 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
1561 % (s, ' '.join(self.asVirtModesDef)));
1562
1563 elif asArgs[iArg] == '--skip-virt-modes':
1564 iArg += 1;
1565 if iArg >= len(asArgs):
1566 raise base.InvalidOption('The "--skip-virt-modes" takes a colon separated list of modes');
1567
1568 for s in asArgs[iArg].split(':'):
1569 if s not in self.asVirtModesDef:
1570 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
1571 % (s, ' '.join(self.asVirtModesDef)));
1572 if s in self.asVirtModes:
1573 self.asVirtModes.remove(s);
1574
1575 elif asArgs[iArg] == '--cpu-counts':
1576 iArg += 1;
1577 if iArg >= len(asArgs):
1578 raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
1579
1580 self.acCpus = [];
1581 for s in asArgs[iArg].split(':'):
1582 try: c = int(s);
1583 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
1584 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
1585 self.acCpus.append(c);
1586
1587 elif asArgs[iArg] == '--test-vms':
1588 iArg += 1;
1589 if iArg >= len(asArgs):
1590 raise base.InvalidOption('The "--test-vms" takes colon separated list');
1591
1592 for oTestVm in self.aoTestVms:
1593 oTestVm.fSkip = True;
1594
1595 asTestVMs = asArgs[iArg].split(':');
1596 for s in asTestVMs:
1597 oTestVm = self.findTestVmByName(s);
1598 if oTestVm is None:
1599 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
1600 % (s, self.getAllVmNames(' ')));
1601 oTestVm.fSkip = False;
1602
1603 elif asArgs[iArg] == '--skip-vms':
1604 iArg += 1;
1605 if iArg >= len(asArgs):
1606 raise base.InvalidOption('The "--skip-vms" takes colon separated list');
1607
1608 asTestVMs = asArgs[iArg].split(':');
1609 for s in asTestVMs:
1610 oTestVm = self.findTestVmByName(s);
1611 if oTestVm is None:
1612 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s,));
1613 else:
1614 oTestVm.fSkip = True;
1615
1616 elif asArgs[iArg] == '--snapshot-restore-current':
1617 for oTestVm in self.aoTestVms:
1618 if oTestVm.fSkip is False:
1619 oTestVm.fSnapshotRestoreCurrent = True;
1620 reporter.log('VM "%s" will be restored.' % (oTestVm.sVmName));
1621
1622 elif asArgs[iArg] == '--paravirt-modes':
1623 iArg += 1
1624 if iArg >= len(asArgs):
1625 raise base.InvalidOption('The "--paravirt-modes" takes a colon separated list of modes');
1626
1627 self.asParavirtModes = asArgs[iArg].split(':')
1628 for sPvMode in self.asParavirtModes:
1629 if sPvMode not in g_kasParavirtProviders:
1630 raise base.InvalidOption('The "--paravirt-modes" value "%s" is not valid; valid values are: %s'
1631 % (sPvMode, ', '.join(g_kasParavirtProviders),));
1632 if not self.asParavirtModes:
1633 self.asParavirtModes = None;
1634
1635 # HACK ALERT! Reset the random paravirt selection for members.
1636 for oTestVm in self.aoTestVms:
1637 oTestVm.asParavirtModesSup = oTestVm.asParavirtModesSupOrg;
1638
1639 elif asArgs[iArg] == '--with-nested-hwvirt-only':
1640 for oTestVm in self.aoTestVms:
1641 if oTestVm.fNstHwVirt is False:
1642 oTestVm.fSkip = True;
1643
1644 elif asArgs[iArg] == '--without-nested-hwvirt-only':
1645 for oTestVm in self.aoTestVms:
1646 if oTestVm.fNstHwVirt is True:
1647 oTestVm.fSkip = True;
1648
1649 else:
1650 return iArg;
1651 return iArg + 1;
1652
1653 def getResourceSet(self):
1654 """
1655 Called vbox.TestDriver.getResourceSet and returns a list of paths of resources.
1656 """
1657 asResources = [];
1658 for oTestVm in self.aoTestVms:
1659 if not oTestVm.fSkip:
1660 if isinstance(oTestVm, BaseTestVm): # Temporarily...
1661 asResources.extend(oTestVm.getResourceSet());
1662 else:
1663 if oTestVm.sHd is not None:
1664 asResources.append(oTestVm.sHd);
1665 if oTestVm.sDvdImage is not None:
1666 asResources.append(oTestVm.sDvdImage);
1667 return asResources;
1668
1669 def actionConfig(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
1670 """
1671 For base.TestDriver.actionConfig. Configure the VMs with defaults and
1672 a few tweaks as per arguments.
1673
1674 Returns True if successful.
1675 Returns False if not.
1676 """
1677
1678 for oTestVm in self.aoTestVms:
1679 if oTestVm.fSkip:
1680 continue;
1681 if oTestVm.skipCreatingVm(oTestDrv):
1682 oTestVm.fSkip = True;
1683 continue;
1684
1685 if oTestVm.fSnapshotRestoreCurrent:
1686 # If we want to restore a VM we don't need to create
1687 # the machine anymore -- so just add it to the test VM list.
1688 oVM = oTestDrv.addTestMachine(oTestVm.sVmName);
1689 else:
1690 oVM = oTestVm.createVm(oTestDrv, eNic0AttachType, sDvdImage);
1691 if oVM is None:
1692 return False;
1693
1694 return True;
1695
1696 def _removeUnsupportedVirtModes(self, oTestDrv):
1697 """
1698 Removes unsupported virtualization modes.
1699 """
1700 if 'hwvirt' in self.asVirtModes and not oTestDrv.hasHostHwVirt():
1701 reporter.log('Hardware assisted virtualization is not available on the host, skipping it.');
1702 self.asVirtModes.remove('hwvirt');
1703
1704 if 'hwvirt-np' in self.asVirtModes and not oTestDrv.hasHostNestedPaging():
1705 reporter.log('Nested paging not supported by the host, skipping it.');
1706 self.asVirtModes.remove('hwvirt-np');
1707
1708 if 'raw' in self.asVirtModes and not oTestDrv.hasRawModeSupport():
1709 reporter.log('Raw-mode virtualization is not available in this build (or perhaps for this host), skipping it.');
1710 self.asVirtModes.remove('raw');
1711
1712 return True;
1713
1714 def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=too-many-locals
1715 """
1716 For base.TestDriver.actionExecute. Calls the callback function for
1717 each of the VMs and basic configuration variations (virt-mode and cpu
1718 count).
1719
1720 Returns True if all fnCallback calls returned True, otherwise False.
1721
1722 The callback can return True, False or None. The latter is for when the
1723 test is skipped. (True is for success, False is for failure.)
1724 """
1725
1726 self._removeUnsupportedVirtModes(oTestDrv);
1727 cMaxCpus = oTestDrv.getHostCpuCount();
1728
1729 #
1730 # The test loop.
1731 #
1732 fRc = True;
1733 for oTestVm in self.aoTestVms:
1734 if oTestVm.fSkip and self.fIgnoreSkippedVm:
1735 reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,));
1736 continue;
1737 reporter.testStart(oTestVm.sVmName);
1738 if oTestVm.fSkip:
1739 reporter.testDone(fSkipped = True);
1740 continue;
1741
1742 # Intersect the supported modes and the ones being testing.
1743 asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes];
1744
1745 # Ditto for CPUs.
1746 acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus];
1747
1748 # Ditto for paravirtualization modes, except if not specified we got a less obvious default.
1749 if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0:
1750 asParavirtModes = [sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes];
1751 assert None not in asParavirtModes;
1752 elif oTestDrv.fpApiVer >= 5.0:
1753 asParavirtModes = (oTestVm.asParavirtModesSup[0],);
1754 assert asParavirtModes[0] is not None;
1755 else:
1756 asParavirtModes = (None,);
1757
1758 for cCpus in acCpusSup:
1759 if cCpus == 1:
1760 reporter.testStart('1 cpu');
1761 else:
1762 reporter.testStart('%u cpus' % (cCpus));
1763 if cCpus > cMaxCpus:
1764 reporter.testDone(fSkipped = True);
1765 continue;
1766
1767 cTests = 0;
1768 for sVirtMode in asVirtModesSup:
1769 if sVirtMode == 'raw' and cCpus > 1:
1770 continue;
1771 reporter.testStart('%s' % ( g_dsVirtModeDescs[sVirtMode], ) );
1772 cStartTests = cTests;
1773
1774 for sParavirtMode in asParavirtModes:
1775 if sParavirtMode is not None:
1776 assert oTestDrv.fpApiVer >= 5.0;
1777 reporter.testStart('%s' % ( sParavirtMode, ) );
1778
1779 # Reconfigure the VM.
1780 try:
1781 (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode = sParavirtMode);
1782 except KeyboardInterrupt:
1783 raise;
1784 except:
1785 reporter.errorXcpt(cFrames = 9);
1786 rc2 = False;
1787 if rc2 is True:
1788 # Do the testing.
1789 try:
1790 rc2 = fnCallback(oVM, oTestVm);
1791 except KeyboardInterrupt:
1792 raise;
1793 except:
1794 reporter.errorXcpt(cFrames = 9);
1795 rc2 = False;
1796 if rc2 is False:
1797 reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed');
1798 elif rc2 is False:
1799 reporter.log('getReconfiguredVm failed');
1800 if rc2 is False:
1801 fRc = False;
1802
1803 cTests = cTests + (rc2 is not None);
1804 if sParavirtMode is not None:
1805 reporter.testDone(fSkipped = (rc2 is None));
1806
1807 reporter.testDone(fSkipped = cTests == cStartTests);
1808
1809 reporter.testDone(fSkipped = cTests == 0);
1810
1811 _, cErrors = reporter.testDone();
1812 if cErrors > 0:
1813 fRc = False;
1814 return fRc;
1815
1816 def enumerateTestVms(self, fnCallback):
1817 """
1818 Enumerates all the 'active' VMs.
1819
1820 Returns True if all fnCallback calls returned True.
1821 Returns False if any returned False.
1822 Returns None immediately if fnCallback returned None.
1823 """
1824 fRc = True;
1825 for oTestVm in self.aoTestVms:
1826 if not oTestVm.fSkip:
1827 fRc2 = fnCallback(oTestVm);
1828 if fRc2 is None:
1829 return fRc2;
1830 fRc = fRc and fRc2;
1831 return fRc;
1832
1833
1834
1835class TestVmManager(object):
1836 """
1837 Test VM manager.
1838 """
1839
1840 ## @name VM grouping flags
1841 ## @{
1842 kfGrpSmoke = g_kfGrpSmoke;
1843 kfGrpStandard = g_kfGrpStandard;
1844 kfGrpStdSmoke = g_kfGrpStdSmoke;
1845 kfGrpWithGAs = g_kfGrpWithGAs;
1846 kfGrpNoTxs = g_kfGrpNoTxs;
1847 kfGrpAncient = g_kfGrpAncient;
1848 kfGrpExotic = g_kfGrpExotic;
1849 ## @}
1850
1851 kaTestVMs = (
1852 # Linux
1853 TestVm('tst-ubuntu-15_10-64-efi', kfGrpStdSmoke, sHd = '4.2/efi/ubuntu-15_10-efi-amd64.vdi',
1854 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi',
1855 asParavirtModesSup = [g_ksParavirtProviderKVM,]),
1856 TestVm('tst-rhel5', kfGrpSmoke, sHd = '3.0/tcp/rhel5.vdi',
1857 sKind = 'RedHat', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat'),
1858 TestVm('tst-arch', kfGrpStandard, sHd = '4.2/usb/tst-arch.vdi',
1859 sKind = 'ArchLinux_64', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat'),
1860 # disabled 2019-03-08 klaus - fails all over the place and pollutes the test results
1861 #TestVm('tst-ubuntu-1804-64', kfGrpStdSmoke, sHd = '4.2/ubuntu-1804/t-ubuntu-1804-64.vdi',
1862 # sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True),
1863 TestVm('tst-ol76-64', kfGrpStdSmoke, sHd = '4.2/ol76/t-ol76-64.vdi',
1864 sKind = 'Oracle_64', acCpusSup = range(1, 33), fIoApic = True),
1865
1866 # Solaris
1867 TestVm('tst-sol10', kfGrpSmoke, sHd = '3.0/tcp/solaris10.vdi',
1868 sKind = 'Solaris', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged'),
1869 TestVm('tst-sol10-64', kfGrpSmoke, sHd = '3.0/tcp/solaris10.vdi',
1870 sKind = 'Solaris_64', acCpusSup = range(1, 33), sNic0AttachType = 'bridged'),
1871 TestVm('tst-sol11u1', kfGrpSmoke, sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
1872 sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat', fIoApic = True,
1873 sHddControllerType = 'SATA Controller'),
1874 #TestVm('tst-sol11u1-ich9', kfGrpSmoke, sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
1875 # sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat', fIoApic = True,
1876 # sHddControllerType = 'SATA Controller', sChipsetType = 'ich9'),
1877
1878 # NT 3.x
1879 TestVm('tst-nt310', kfGrpAncient, sHd = '5.2/great-old-ones/t-nt310/t-nt310.vdi',
1880 sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
1881 sDvdControllerType = 'BusLogic SCSI Controller'),
1882 TestVm('tst-nt350', kfGrpAncient, sHd = '5.2/great-old-ones/t-nt350/t-nt350.vdi',
1883 sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
1884 sDvdControllerType = 'BusLogic SCSI Controller'),
1885 TestVm('tst-nt351', kfGrpAncient, sHd = '5.2/great-old-ones/t-nt350/t-nt351.vdi',
1886 sKind = 'WindowsNT3x', acCpusSup = [1], sHddControllerType = 'BusLogic SCSI Controller',
1887 sDvdControllerType = 'BusLogic SCSI Controller'),
1888
1889 # NT 4
1890 TestVm('tst-nt4sp1', kfGrpStdSmoke, sHd = '4.2/nat/nt4sp1/t-nt4sp1.vdi',
1891 sKind = 'WindowsNT4', acCpusSup = [1], sNic0AttachType = 'nat'),
1892
1893 TestVm('tst-nt4sp6', kfGrpStdSmoke, sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
1894 sKind = 'WindowsNT4', acCpusSup = range(1, 33)),
1895
1896 # W2K
1897 TestVm('tst-2ksp4', kfGrpStdSmoke, sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
1898 sKind = 'Windows2000', acCpusSup = range(1, 33)),
1899
1900 # XP
1901 TestVm('tst-xppro', kfGrpStdSmoke, sHd = '4.2/nat/xppro/t-xppro.vdi',
1902 sKind = 'WindowsXP', acCpusSup = range(1, 33), sNic0AttachType = 'nat'),
1903 TestVm('tst-xpsp2', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxpsp2.vdi',
1904 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1905 TestVm('tst-xpsp2-halaacpi', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
1906 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1907 TestVm('tst-xpsp2-halacpi', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
1908 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1909 TestVm('tst-xpsp2-halapic', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
1910 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True),
1911 TestVm('tst-xpsp2-halmacpi', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
1912 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True),
1913 TestVm('tst-xpsp2-halmps', kfGrpStdSmoke, sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
1914 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True),
1915
1916 # W2K3
1917 TestVm('tst-win2k3ent', kfGrpSmoke, sHd = '3.0/tcp/win2k3ent-acpi.vdi',
1918 sKind = 'Windows2003', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged'),
1919
1920 # W7
1921 TestVm('tst-win7', kfGrpStdSmoke, sHd = '4.2/win7-32/t-win7.vdi',
1922 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True),
1923
1924 # W8
1925 TestVm('tst-win8-64', kfGrpStdSmoke, sHd = '4.2/win8-64/t-win8-64.vdi',
1926 sKind = 'Windows8_64', acCpusSup = range(1, 33), fIoApic = True),
1927 #TestVm('tst-win8-64-ich9', kfGrpStdSmoke, sHd = '4.2/win8-64/t-win8-64.vdi',
1928 # sKind = 'Windows8_64', acCpusSup = range(1, 33), fIoApic = True, sChipsetType = 'ich9'),
1929
1930 # W10
1931 TestVm('tst-win10-efi', kfGrpStdSmoke, sHd = '4.2/efi/win10-efi-x86.vdi',
1932 sKind = 'Windows10', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi'),
1933 TestVm('tst-win10-64-efi', kfGrpStdSmoke, sHd = '4.2/efi/win10-efi-amd64.vdi',
1934 sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi'),
1935 #TestVm('tst-win10-64-efi-ich9', kfGrpStdSmoke, sHd = '4.2/efi/win10-efi-amd64.vdi',
1936 # sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi', sChipsetType = 'ich9'),
1937
1938 # Nested hardware-virtualization
1939 TestVm('tst-nsthwvirt-ubuntu-64', kfGrpStdSmoke, sHd = '5.3/nat/nsthwvirt-ubuntu64/t-nsthwvirt-ubuntu64.vdi',
1940 sKind = 'Ubuntu_64', acCpusSup = range(1, 2), asVirtModesSup = ['hwvirt-np',], fIoApic = True, fNstHwVirt = True,
1941 sNic0AttachType = 'nat'),
1942
1943 # DOS and Old Windows.
1944 AncientTestVm('tst-dos20', sKind = 'DOS',
1945 sHd = '5.2/great-old-ones/t-dos20/t-dos20.vdi'),
1946 AncientTestVm('tst-dos401-win30me', sKind = 'DOS',
1947 sHd = '5.2/great-old-ones/t-dos401-win30me/t-dos401-win30me.vdi', cMBRamMax = 4),
1948 AncientTestVm('tst-dos401-emm386-win30me', sKind = 'DOS',
1949 sHd = '5.2/great-old-ones/t-dos401-emm386-win30me/t-dos401-emm386-win30me.vdi', cMBRamMax = 4),
1950 AncientTestVm('tst-dos50-win31', sKind = 'DOS',
1951 sHd = '5.2/great-old-ones/t-dos50-win31/t-dos50-win31.vdi'),
1952 AncientTestVm('tst-dos50-emm386-win31', sKind = 'DOS',
1953 sHd = '5.2/great-old-ones/t-dos50-emm386-win31/t-dos50-emm386-win31.vdi'),
1954 AncientTestVm('tst-dos622', sKind = 'DOS',
1955 sHd = '5.2/great-old-ones/t-dos622/t-dos622.vdi'),
1956 AncientTestVm('tst-dos622-emm386', sKind = 'DOS',
1957 sHd = '5.2/great-old-ones/t-dos622-emm386/t-dos622-emm386.vdi'),
1958 AncientTestVm('tst-dos71', sKind = 'DOS',
1959 sHd = '5.2/great-old-ones/t-dos71/t-dos71.vdi'),
1960
1961 #AncientTestVm('tst-dos5-win311a', sKind = 'DOS', sHd = '5.2/great-old-ones/t-dos5-win311a/t-dos5-win311a.vdi'),
1962 );
1963
1964
1965 def __init__(self, sResourcePath):
1966 self.sResourcePath = sResourcePath;
1967
1968 def selectSet(self, fGrouping, sTxsTransport = None, fCheckResources = True):
1969 """
1970 Returns a VM set with the selected VMs.
1971 """
1972 oSet = TestVmSet(oTestVmManager = self);
1973 for oVm in self.kaTestVMs:
1974 if oVm.fGrouping & fGrouping:
1975 if sTxsTransport is None or oVm.sNic0AttachType is None or sTxsTransport == oVm.sNic0AttachType:
1976 if not fCheckResources or not oVm.getMissingResources(self.sResourcePath):
1977 oCopyVm = copy.deepcopy(oVm);
1978 oCopyVm.oSet = oSet;
1979 oSet.aoTestVms.append(oCopyVm);
1980 return oSet;
1981
1982 def getStandardVmSet(self, sTxsTransport):
1983 """
1984 Gets the set of standard test VMs.
1985
1986 This is supposed to do something seriously clever, like searching the
1987 testrsrc tree for usable VMs, but for the moment it's all hard coded. :-)
1988 """
1989 return self.selectSet(self.kfGrpStandard, sTxsTransport)
1990
1991 def getSmokeVmSet(self, sTxsTransport = None):
1992 """Gets a representative set of VMs for smoke testing. """
1993 return self.selectSet(self.kfGrpSmoke, sTxsTransport);
1994
1995 def shutUpPyLint(self):
1996 """ Shut up already! """
1997 return self.sResourcePath;
1998
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