VirtualBox

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

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

tdAddGuestCtrl.py: More cleanups. bugref:9151 bugref:9320

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