VirtualBox

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

Last change on this file since 79185 was 79180, checked in by vboxsync, 6 years ago

tdAddGuestCtrl.py: testGuestCtrlCopyFrom related cleanups. Fixed python 2.x issue in vboxtestfileset.py. bugref:9151 bugref:9320

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette