VirtualBox

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

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

vboxtestvms.py: Typo. bugref:9320 bugref:9151

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