VirtualBox

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

Last change on this file since 79066 was 79046, checked in by vboxsync, 6 years ago

ValKit/tdGuestOsUnattendedInst1.py: Got basics working. bugref:9151

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