VirtualBox

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

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

vboxtestvms.py: Array getting fixes. bugref:9320 bugref:9151

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