VirtualBox

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

最後變更 在這個檔案從79087是 79087,由 vboxsync 提交於 6 年 前

ValKit: New pylint version - cleanup in progress.

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

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