VirtualBox

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

Last change on this file since 61750 was 61750, checked in by vboxsync, 9 years ago

ValidationKit: enable I/O-APIC if VCPUs > 1

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 44.3 KB
Line 
1# -*- coding: utf-8 -*-
2# $Id: vboxtestvms.py 61750 2016-06-17 14:59:05Z vboxsync $
3
4"""
5VirtualBox Test VMs
6"""
7
8__copyright__ = \
9"""
10Copyright (C) 2010-2015 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: 61750 $"
30
31# Standard Python imports.
32import re;
33import random;
34import socket;
35
36# Validation Kit imports.
37from testdriver import base;
38from testdriver import reporter;
39from testdriver import vboxcon;
40
41
42# All virtualization modes.
43g_asVirtModes = ['hwvirt', 'hwvirt-np', 'raw',];
44# All virtualization modes except for raw-mode.
45g_asVirtModesNoRaw = ['hwvirt', 'hwvirt-np',];
46# Dictionary mapping the virtualization mode mnemonics to a little less cryptic
47# strings used in test descriptions.
48g_dsVirtModeDescs = {
49 'raw' : 'Raw-mode',
50 'hwvirt' : 'HwVirt',
51 'hwvirt-np' : 'NestedPaging'
52};
53
54## @name Flags.
55## @{
56g_k32 = 32; # pylint: disable=C0103
57g_k64 = 64; # pylint: disable=C0103
58g_k32_64 = 96; # pylint: disable=C0103
59g_kiArchMask = 96;
60g_kiNoRaw = 128; ##< No raw mode.
61## @}
62
63# Array indexes.
64g_iGuestOsType = 0;
65g_iKind = 1;
66g_iFlags = 2;
67g_iMinCpu = 3;
68g_iMaxCpu = 4;
69g_iRegEx = 5;
70
71# Table translating from VM name core to a more detailed guest info.
72# pylint: disable=C0301
73g_aaNameToDetails = \
74[
75 [ 'WindowsNT4', 'WindowsNT4', g_k32, 1, 32, ['nt4', 'nt4sp[0-9]']], # max cpus??
76 [ 'Windows2000', 'Windows2000', g_k32, 1, 32, ['w2k', 'w2ksp[0-9]', 'win2k', 'win2ksp[0-9]']], # max cpus??
77 [ 'WindowsXP', 'WindowsXP', g_k32, 1, 32, ['xp', 'xpsp[0-9]']],
78 [ 'WindowsXP_64', 'WindowsXP_64', g_k64, 1, 32, ['xp64', 'xp64sp[0-9]']],
79 [ 'Windows2003', 'Windows2003', g_k32, 1, 32, ['w2k3', 'w2k3sp[0-9]', 'win2k3', 'win2k3sp[0-9]']],
80 [ 'WindowsVista', 'WindowsVista', g_k32, 1, 32, ['vista', 'vistasp[0-9]']],
81 [ 'Windows2008', 'Windows2008', g_k32, 1, 64, ['w2k8', 'w2k8sp[0-9]', 'win2k8', 'win2k8sp[0-9]']], # max cpus/cores??
82 [ 'Windows2008_64', 'Windows2008_64', g_k64, 1, 64, ['w2k8r2', 'w2k8r2sp[0-9]', 'win2k8r2', 'win2k8r2sp[0-9]']], # max cpus/cores??
83 [ 'Windows7', 'Windows7', g_k32, 1, 32, ['w7', 'w7sp[0-9]', 'win7',]], # max cpus/cores??
84 [ 'Windows7_64', 'Windows7_64', g_k64, 1, 64, ['w7-64', 'w7sp[0-9]-64', 'win7-64',]], # max cpus/cores??
85 [ 'Windows8', 'Windows8', g_k32 | g_kiNoRaw, 1, 32, ['w8', 'w8sp[0-9]', 'win8',]], # max cpus/cores??
86 [ 'Windows8_64', 'Windows8_64', g_k64, 1, 64, ['w8-64', 'w8sp[0-9]-64', 'win8-64',]], # max cpus/cores??
87 [ 'Windows81', 'Windows81', g_k32 | g_kiNoRaw, 1, 32, ['w81', 'w81sp[0-9]', 'win81',]], # max cpus/cores??
88 [ 'Windows81_64', 'Windows81_64', g_k64, 1, 64, ['w81-64', 'w81sp[0-9]-64', 'win81-64',]], # max cpus/cores??
89 [ 'Windows10', 'Windows10', g_k32 | g_kiNoRaw, 1, 32, ['w10', 'w10sp[0-9]', 'win10',]], # max cpus/cores??
90 [ 'Windows10_64', 'Windows10_64', g_k64, 1, 64, ['w10-64', 'w10sp[0-9]-64', 'win10-64',]], # max cpus/cores??
91 [ 'Linux', 'Debian', g_k32, 1, 256, ['deb[0-9]*', 'debian[0-9]*', ]],
92 [ 'Linux_64', 'Debian_64', g_k64, 1, 256, ['deb[0-9]*-64', 'debian[0-9]*-64', ]],
93 [ 'Linux', 'RedHat', g_k32, 1, 256, ['rhel', 'rhel[0-9]', 'rhel[0-9]u[0-9]']],
94 [ 'Linux', 'Fedora', g_k32, 1, 256, ['fedora', 'fedora[0-9]*', ]],
95 [ 'Linux_64', 'Fedora_64', g_k64, 1, 256, ['fedora-64', 'fedora[0-9]*-64', ]],
96 [ 'Linux', 'Oracle', g_k32, 1, 256, ['ols[0-9]*', 'oel[0-9]*', ]],
97 [ 'Linux_64', 'Oracle_64', g_k64, 1, 256, ['ols[0-9]*-64', 'oel[0-9]*-64', ]],
98 [ 'Linux', 'OpenSUSE', g_k32, 1, 256, ['opensuse[0-9]*', 'suse[0-9]*', ]],
99 [ 'Linux_64', 'OpenSUSE_64', g_k64, 1, 256, ['opensuse[0-9]*-64', 'suse[0-9]*-64', ]],
100 [ 'Linux', 'Ubuntu', g_k32, 1, 256, ['ubuntu[0-9]*', ]],
101 [ 'Linux_64', 'Ubuntu_64', g_k64, 1, 256, ['ubuntu[0-9]*-64', ]],
102 [ 'Solaris', 'Solaris', g_k32, 1, 256, ['sol10', 'sol10u[0-9]']],
103 [ 'Solaris_64', 'Solaris_64', g_k64, 1, 256, ['sol10-64', 'sol10u-64[0-9]']],
104 [ 'Solaris_64', 'Solaris11_64', g_k64, 1, 256, ['sol11u1']],
105 [ 'BSD', 'FreeBSD_64', g_k32_64, 1, 1, ['bs-.*']], # boot sectors, wanted 64-bit type.
106];
107
108
109## @name Guest OS type string constants.
110## @{
111g_ksGuestOsTypeDarwin = 'darwin';
112g_ksGuestOsTypeFreeBSD = 'freebsd';
113g_ksGuestOsTypeLinux = 'linux';
114g_ksGuestOsTypeOS2 = 'os2';
115g_ksGuestOsTypeSolaris = 'solaris';
116g_ksGuestOsTypeWindows = 'windows';
117## @}
118
119## @name String constants for paravirtualization providers.
120## @{
121g_ksParavirtProviderNone = 'none';
122g_ksParavirtProviderDefault = 'default';
123g_ksParavirtProviderLegacy = 'legacy';
124g_ksParavirtProviderMinimal = 'minimal';
125g_ksParavirtProviderHyperV = 'hyperv';
126g_ksParavirtProviderKVM = 'kvm';
127## @}
128
129## Valid paravirtualization providers.
130g_kasParavirtProviders = ( g_ksParavirtProviderNone, g_ksParavirtProviderDefault, g_ksParavirtProviderLegacy,
131 g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM );
132
133# Mapping for support of paravirtualisation providers per guest OS.
134#g_kdaParavirtProvidersSupported = {
135# g_ksGuestOsTypeDarwin : ( g_ksParavirtProviderMinimal, ),
136# g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, ),
137# g_ksGuestOsTypeLinux : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
138# g_ksGuestOsTypeOS2 : ( g_ksParavirtProviderNone, ),
139# g_ksGuestOsTypeSolaris : ( g_ksParavirtProviderNone, ),
140# g_ksGuestOsTypeWindows : ( g_ksParavirtProviderNone, g_ksParavirtProviderMinimal, g_ksParavirtProviderHyperV, )
141#}
142# Temporary tweak:
143# since for the most guests g_ksParavirtProviderNone is almost the same as g_ksParavirtProviderMinimal,
144# g_ksParavirtProviderMinimal is removed from the list in order to get maximum number of unique choices
145# during independent test runs when paravirt provider is taken randomly.
146g_kdaParavirtProvidersSupported = {
147 g_ksGuestOsTypeDarwin : ( g_ksParavirtProviderMinimal, ),
148 g_ksGuestOsTypeFreeBSD : ( g_ksParavirtProviderNone, ),
149 g_ksGuestOsTypeLinux : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, g_ksParavirtProviderKVM),
150 g_ksGuestOsTypeOS2 : ( g_ksParavirtProviderNone, ),
151 g_ksGuestOsTypeSolaris : ( g_ksParavirtProviderNone, ),
152 g_ksGuestOsTypeWindows : ( g_ksParavirtProviderNone, g_ksParavirtProviderHyperV, )
153}
154
155
156# pylint: enable=C0301
157
158def _intersects(asSet1, asSet2):
159 """
160 Checks if any of the strings in set 1 matches any of the regular
161 expressions in set 2.
162 """
163 for sStr1 in asSet1:
164 for sRx2 in asSet2:
165 if re.match(sStr1, sRx2 + '$'):
166 return True;
167 return False;
168
169
170class TestVm(object):
171 """
172 A Test VM - name + VDI/whatever.
173
174 This is just a data object.
175 """
176
177 def __init__(self, oSet, sVmName, sHd = None, sKind = None, acCpusSup = None, asVirtModesSup = None, # pylint: disable=R0913
178 fIoApic = None, fPae = None, sNic0AttachType = None, sHddControllerType = 'IDE Controller',
179 sFloppy = None, fVmmDevTestingPart = None, fVmmDevTestingMmio = False, asParavirtModesSup = None,
180 fRandomPvPMode = False, sFirmwareType = 'bios'):
181 self.oSet = oSet;
182 self.sVmName = sVmName;
183 self.sHd = sHd; # Relative to the testrsrc root.
184 self.acCpusSup = acCpusSup;
185 self.asVirtModesSup = asVirtModesSup;
186 self.asParavirtModesSup = asParavirtModesSup;
187 self.sKind = sKind;
188 self.sGuestOsType = None;
189 self.sDvdImage = None; # Relative to the testrsrc root.
190 self.fIoApic = fIoApic;
191 self.fPae = fPae;
192 self.sNic0AttachType = sNic0AttachType;
193 self.sHddControllerType = sHddControllerType;
194 self.sFloppy = sFloppy; # Relative to the testrsrc root, except when it isn't...
195 self.fVmmDevTestingPart = fVmmDevTestingPart;
196 self.fVmmDevTestingMmio = fVmmDevTestingMmio;
197 self.sFirmwareType = sFirmwareType;
198
199 self.fSnapshotRestoreCurrent = False; # Whether to restore execution on the current snapshot.
200 self.fSkip = False; # All VMs are included in the configured set by default.
201 self.aInfo = None;
202 self._guessStuff(fRandomPvPMode);
203
204 def _mkCanonicalGuestOSType(self, sType):
205 """
206 Convert guest OS type into constant representation.
207 Raise exception if specified @param sType is unknown.
208 """
209 if sType.lower().startswith('darwin'):
210 return g_ksGuestOsTypeDarwin
211 if sType.lower().startswith('bsd'):
212 return g_ksGuestOsTypeFreeBSD
213 if sType.lower().startswith('linux'):
214 return g_ksGuestOsTypeLinux
215 if sType.lower().startswith('os2'):
216 return g_ksGuestOsTypeOS2
217 if sType.lower().startswith('solaris'):
218 return g_ksGuestOsTypeSolaris
219 if sType.lower().startswith('windows'):
220 return g_ksGuestOsTypeWindows
221 raise base.GenError(sWhat="unknown guest OS kind: %s" % str(sType))
222
223 def _guessStuff(self, fRandomPvPMode):
224 """
225 Used by the constructor to guess stuff.
226 """
227
228 sNm = self.sVmName.lower().strip();
229 asSplit = sNm.replace('-', ' ').split(' ');
230
231 if self.sKind is None:
232 # From name.
233 for aInfo in g_aaNameToDetails:
234 if _intersects(asSplit, aInfo[g_iRegEx]):
235 self.aInfo = aInfo;
236 self.sGuestOsType = self._mkCanonicalGuestOSType(aInfo[g_iGuestOsType])
237 self.sKind = aInfo[g_iKind];
238 break;
239 if self.sKind is None:
240 reporter.fatal('The OS of test VM "%s" cannot be guessed' % (self.sVmName,));
241
242 # Check for 64-bit, if required and supported.
243 if (self.aInfo[g_iFlags] & g_kiArchMask) == g_k32_64 and _intersects(asSplit, ['64', 'amd64']):
244 self.sKind = self.sKind + '_64';
245 else:
246 # Lookup the kind.
247 for aInfo in g_aaNameToDetails:
248 if self.sKind == aInfo[g_iKind]:
249 self.aInfo = aInfo;
250 break;
251 if self.aInfo is None:
252 reporter.fatal('The OS of test VM "%s" with sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
253
254 # Translate sKind into sGuest OS Type.
255 if self.sGuestOsType is None:
256 if self.aInfo is not None:
257 self.sGuestOsType = self._mkCanonicalGuestOSType(self.aInfo[g_iGuestOsType])
258 elif self.sKind.find("Windows") >= 0:
259 self.sGuestOsType = g_ksGuestOsTypeWindows
260 elif self.sKind.find("Linux") >= 0:
261 self.sGuestOsType = g_ksGuestOsTypeLinux;
262 elif self.sKind.find("Solaris") >= 0:
263 self.sGuestOsType = g_ksGuestOsTypeSolaris;
264 else:
265 reporter.fatal('The OS of test VM "%s", sKind="%s" cannot be guessed' % (self.sVmName, self.sKind));
266
267 # Restrict modes and such depending on the OS.
268 if self.asVirtModesSup is None:
269 self.asVirtModesSup = list(g_asVirtModes);
270 if self.sGuestOsType in (g_ksGuestOsTypeOS2, g_ksGuestOsTypeDarwin) \
271 or self.sKind.find('_64') > 0 \
272 or (self.aInfo is not None and (self.aInfo[g_iFlags] & g_kiNoRaw)):
273 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
274 # TEMPORARY HACK - START
275 sHostName = socket.getfqdn();
276 if sHostName.startswith('testboxpile1'):
277 self.asVirtModesSup = [sVirtMode for sVirtMode in self.asVirtModesSup if sVirtMode != 'raw'];
278 # TEMPORARY HACK - END
279
280 # Restrict the CPU count depending on the OS and/or percieved SMP readiness.
281 if self.acCpusSup is None:
282 if _intersects(asSplit, ['uni']):
283 self.acCpusSup = [1];
284 elif self.aInfo is not None:
285 self.acCpusSup = [i for i in range(self.aInfo[g_iMinCpu], self.aInfo[g_iMaxCpu]) ];
286 else:
287 self.acCpusSup = [1];
288
289 # Figure relevant PV modes based on the OS.
290 if self.asParavirtModesSup is None:
291 self.asParavirtModesSup = g_kdaParavirtProvidersSupported[self.sGuestOsType];
292 ## @todo Remove this hack as soon as we've got around to explictly configure test variations
293 ## on the server side. Client side random is interesting but not the best option.
294 if fRandomPvPMode:
295 random.seed();
296 self.asParavirtModesSup = (random.choice(self.asParavirtModesSup),);
297
298 return True;
299
300 def getReconfiguredVm(self, oTestDrv, cCpus, sVirtMode, sParavirtMode = None):
301 """
302 actionExecute worker that finds and reconfigure a test VM.
303
304 Returns (fRc, oVM) where fRc is True, None or False and oVM is a
305 VBox VM object that is only present when rc is True.
306 """
307
308 fRc = False;
309 oVM = oTestDrv.getVmByName(self.sVmName);
310 if oVM is not None:
311 if self.fSnapshotRestoreCurrent is True:
312 fRc = True;
313 else:
314 fHostSupports64bit = oTestDrv.hasHostLongMode();
315 if self.is64bitRequired() and not fHostSupports64bit:
316 fRc = None; # Skip the test.
317 elif self.isViaIncompatible() and oTestDrv.isHostCpuVia():
318 fRc = None; # Skip the test.
319 else:
320 oSession = oTestDrv.openSession(oVM);
321 if oSession is not None:
322 fRc = oSession.enableVirtEx(sVirtMode != 'raw');
323 fRc = fRc and oSession.enableNestedPaging(sVirtMode == 'hwvirt-np');
324 fRc = fRc and oSession.setCpuCount(cCpus);
325 fRc = fRc and oSession.enableIoApic(cCpus > 1);
326
327 if sParavirtMode is not None and oSession.fpApiVer >= 5.0:
328 adParavirtProviders = {
329 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None,
330 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default,
331 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy,
332 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal,
333 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV,
334 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM,
335 };
336 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]);
337
338 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw');
339 fRc = fRc and oSession.enableLongMode(fCfg64Bit);
340 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh.
341 oOsType = oSession.getOsType();
342 if oOsType is not None:
343 if oOsType.is64Bit and sVirtMode == 'raw':
344 assert(oOsType.id[-3:] == '_64');
345 fRc = fRc and oSession.setOsType(oOsType.id[:-3]);
346 elif not oOsType.is64Bit and sVirtMode != 'raw':
347 fRc = fRc and oSession.setOsType(oOsType.id + '_64');
348
349 fRc = fRc and oSession.saveSettings();
350 if not oSession.close():
351 fRc = False;
352 if fRc is True:
353 return (True, oVM);
354 return (fRc, None);
355
356
357 def isWindows(self):
358 """ Checks if it's a Windows VM. """
359 return self.sGuestOsType == g_ksGuestOsTypeWindows;
360
361 def isOS2(self):
362 """ Checks if it's an OS/2 VM. """
363 return self.sGuestOsType == g_ksGuestOsTypeOS2;
364
365 def is64bit(self):
366 """ Checks if it's a 64-bit VM. """
367 return self.sKind.find('_64') >= 0;
368
369 def is64bitRequired(self):
370 """ Check if 64-bit is required or not. """
371 return (self.aInfo[g_iFlags] & g_k64) != 0;
372
373 def isLoggedOntoDesktop(self):
374 """ Checks if the test VM is logging onto a graphical desktop by default. """
375 if self.isWindows():
376 return True;
377 if self.isOS2():
378 return True;
379 if self.sVmName.find('-desktop'):
380 return True;
381 return False;
382
383 def isViaIncompatible(self):
384 """
385 Identifies VMs that doesn't work on VIA.
386
387 Returns True if NOT supported on VIA, False if it IS supported.
388 """
389 # Oracle linux doesn't like VIA in our experience
390 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
391 return True;
392 # OS/2: "The system detected an internal processing error at location
393 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
394 if self.isOS2():
395 return True;
396 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
397 # detected, leading to a STOP 3e(80,0,0,0).
398 if self.aInfo[g_iKind] == 'WindowsNT4':
399 if self.sVmName.find('sp') < 0:
400 return True; # no service pack.
401 if self.sVmName.find('sp0') >= 0 \
402 or self.sVmName.find('sp1') >= 0 \
403 or self.sVmName.find('sp2') >= 0 \
404 or self.sVmName.find('sp3') >= 0:
405 return True;
406 return False;
407
408
409
410class BootSectorTestVm(TestVm):
411 """
412 A Boot Sector Test VM.
413 """
414
415 def __init__(self, oSet, sVmName, sFloppy = None, asVirtModesSup = None, f64BitRequired = False):
416 self.f64BitRequired = f64BitRequired;
417 if asVirtModesSup is None:
418 asVirtModesSup = list(g_asVirtModes);
419 TestVm.__init__(self, oSet, sVmName,
420 acCpusSup = [1,],
421 sFloppy = sFloppy,
422 asVirtModesSup = asVirtModesSup,
423 fPae = True,
424 fIoApic = True,
425 fVmmDevTestingPart = True,
426 fVmmDevTestingMmio = True,
427 );
428
429 def is64bitRequired(self):
430 return self.f64BitRequired;
431
432
433
434class TestVmSet(object):
435 """
436 A set of Test VMs.
437 """
438
439 def __init__(self, oTestVmManager = None, acCpus = None, asVirtModes = None, fIgnoreSkippedVm = False):
440 self.oTestVmManager = oTestVmManager;
441 if acCpus is None:
442 acCpus = [1, 2];
443 self.acCpusDef = acCpus;
444 self.acCpus = acCpus;
445 if asVirtModes is None:
446 asVirtModes = list(g_asVirtModes);
447 self.asVirtModesDef = asVirtModes;
448 self.asVirtModes = asVirtModes;
449 self.aoTestVms = [];
450 self.fIgnoreSkippedVm = fIgnoreSkippedVm;
451 self.asParavirtModes = None; ##< If None, use the first PV mode of the test VM, otherwise all modes in this list.
452
453 def findTestVmByName(self, sVmName):
454 """
455 Returns the TestVm object with the given name.
456 Returns None if not found.
457 """
458 for oTestVm in self.aoTestVms:
459 if oTestVm.sVmName == sVmName:
460 return oTestVm;
461 return None;
462
463 def getAllVmNames(self, sSep = ':'):
464 """
465 Returns names of all the test VMs in the set separated by
466 sSep (defaults to ':').
467 """
468 sVmNames = '';
469 for oTestVm in self.aoTestVms:
470 if sVmNames == '':
471 sVmNames = oTestVm.sVmName;
472 else:
473 sVmNames = sVmNames + sSep + oTestVm.sVmName;
474 return sVmNames;
475
476 def showUsage(self):
477 """
478 Invoked by vbox.TestDriver.
479 """
480 reporter.log('');
481 reporter.log('Test VM selection and general config options:');
482 reporter.log(' --virt-modes <m1[:m2[:]]');
483 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
484 reporter.log(' --skip-virt-modes <m1[:m2[:]]');
485 reporter.log(' Use this to avoid hwvirt or hwvirt-np when not supported by the host');
486 reporter.log(' since we cannot detect it using the main API. Use after --virt-modes.');
487 reporter.log(' --cpu-counts <c1[:c2[:]]');
488 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
489 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
490 reporter.log(' Test the specified VMs in the given order. Use this to change');
491 reporter.log(' the execution order or limit the choice of VMs');
492 reporter.log(' Default: %s (all)' % (self.getAllVmNames(),));
493 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
494 reporter.log(' Skip the specified VMs when testing.');
495 reporter.log(' --snapshot-restore-current');
496 reporter.log(' Restores the current snapshot and resumes execution.');
497 reporter.log(' --paravirt-modes <pv1[:pv2[:]]>');
498 reporter.log(' Set of paravirtualized providers (modes) to tests. Intersected with what the test VM supports.');
499 reporter.log(' Default is the first PV mode the test VMs support, generally same as "legacy".');
500 ## @todo Add more options for controlling individual VMs.
501 return True;
502
503 def parseOption(self, asArgs, iArg):
504 """
505 Parses the set test vm set options (--test-vms and --skip-vms), modifying the set
506 Invoked by the testdriver method with the same name.
507
508 Keyword arguments:
509 asArgs -- The argument vector.
510 iArg -- The index of the current argument.
511
512 Returns iArg if the option was not recognized and the caller should handle it.
513 Returns the index of the next argument when something is consumed.
514
515 In the event of a syntax error, a InvalidOption or QuietInvalidOption
516 is thrown.
517 """
518
519 if asArgs[iArg] == '--virt-modes':
520 iArg += 1;
521 if iArg >= len(asArgs):
522 raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
523
524 self.asVirtModes = asArgs[iArg].split(':');
525 for s in self.asVirtModes:
526 if s not in self.asVirtModesDef:
527 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
528 % (s, ' '.join(self.asVirtModesDef)));
529
530 elif asArgs[iArg] == '--skip-virt-modes':
531 iArg += 1;
532 if iArg >= len(asArgs):
533 raise base.InvalidOption('The "--skip-virt-modes" takes a colon separated list of modes');
534
535 for s in asArgs[iArg].split(':'):
536 if s not in self.asVirtModesDef:
537 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
538 % (s, ' '.join(self.asVirtModesDef)));
539 if s in self.asVirtModes:
540 self.asVirtModes.remove(s);
541
542 elif asArgs[iArg] == '--cpu-counts':
543 iArg += 1;
544 if iArg >= len(asArgs):
545 raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
546
547 self.acCpus = [];
548 for s in asArgs[iArg].split(':'):
549 try: c = int(s);
550 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
551 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
552 self.acCpus.append(c);
553
554 elif asArgs[iArg] == '--test-vms':
555 iArg += 1;
556 if iArg >= len(asArgs):
557 raise base.InvalidOption('The "--test-vms" takes colon separated list');
558
559 for oTestVm in self.aoTestVms:
560 oTestVm.fSkip = True;
561
562 asTestVMs = asArgs[iArg].split(':');
563 for s in asTestVMs:
564 oTestVm = self.findTestVmByName(s);
565 if oTestVm is None:
566 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
567 % (s, self.getAllVmNames(' ')));
568 oTestVm.fSkip = False;
569
570 elif asArgs[iArg] == '--skip-vms':
571 iArg += 1;
572 if iArg >= len(asArgs):
573 raise base.InvalidOption('The "--skip-vms" takes colon separated list');
574
575 asTestVMs = asArgs[iArg].split(':');
576 for s in asTestVMs:
577 oTestVm = self.findTestVmByName(s);
578 if oTestVm is None:
579 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s,));
580 else:
581 oTestVm.fSkip = True;
582
583 elif asArgs[iArg] == '--snapshot-restore-current':
584 for oTestVm in self.aoTestVms:
585 if oTestVm.fSkip is False:
586 oTestVm.fSnapshotRestoreCurrent = True;
587 reporter.log('VM "%s" will be restored.' % (oTestVm.sVmName));
588
589 elif asArgs[iArg] == '--paravirt-modes':
590 iArg += 1
591 if iArg >= len(asArgs):
592 raise base.InvalidOption('The "--paravirt-modes" takes a colon separated list of modes');
593
594 self.asParavirtModes = asArgs[iArg].split(':')
595 for sPvMode in self.asParavirtModes:
596 if sPvMode not in g_kasParavirtProviders:
597 raise base.InvalidOption('The "--paravirt-modes" value "%s" is not valid; valid values are: %s'
598 % (sPvMode, ', '.join(g_kasParavirtProviders),));
599 if len(self.asParavirtModes) == 0:
600 self.asParavirtModes = None;
601
602 else:
603 return iArg;
604 return iArg + 1;
605
606 def getResourceSet(self):
607 """
608 Implements base.TestDriver.getResourceSet
609 """
610 asResources = [];
611 for oTestVm in self.aoTestVms:
612 if not oTestVm.fSkip:
613 if oTestVm.sHd is not None:
614 asResources.append(oTestVm.sHd);
615 if oTestVm.sDvdImage is not None:
616 asResources.append(oTestVm.sDvdImage);
617 return asResources;
618
619 def actionConfig(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
620 """
621 For base.TestDriver.actionConfig. Configure the VMs with defaults and
622 a few tweaks as per arguments.
623
624 Returns True if successful.
625 Returns False if not.
626 """
627
628 for oTestVm in self.aoTestVms:
629 if oTestVm.fSkip:
630 continue;
631
632 if oTestVm.fSnapshotRestoreCurrent:
633 # If we want to restore a VM we don't need to create
634 # the machine anymore -- so just add it to the test VM list.
635 oVM = oTestDrv.addTestMachine(oTestVm.sVmName);
636 else:
637 ## @todo This could possibly be moved to the TestVM object.
638 if sDvdImage is not None:
639 sMyDvdImage = sDvdImage;
640 else:
641 sMyDvdImage = oTestVm.sDvdImage;
642
643 if eNic0AttachType is not None:
644 eMyNic0AttachType = eNic0AttachType;
645 elif oTestVm.sNic0AttachType is None:
646 eMyNic0AttachType = None;
647 elif oTestVm.sNic0AttachType == 'nat':
648 eMyNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
649 elif oTestVm.sNic0AttachType == 'bridged':
650 eMyNic0AttachType = vboxcon.NetworkAttachmentType_Bridged;
651 else:
652 assert False, oTestVm.sNic0AttachType;
653
654 oVM = oTestDrv.createTestVM(oTestVm.sVmName, 1, \
655 sHd = oTestVm.sHd, \
656 sKind = oTestVm.sKind, \
657 fIoApic = oTestVm.fIoApic, \
658 fPae = oTestVm.fPae, \
659 eNic0AttachType = eMyNic0AttachType, \
660 sDvdImage = sMyDvdImage, \
661 sHddControllerType = oTestVm.sHddControllerType,
662 sFloppy = oTestVm.sFloppy,
663 fVmmDevTestingPart = oTestVm.fVmmDevTestingPart,
664 fVmmDevTestingMmio = oTestVm.fVmmDevTestingPart,
665 sFirmwareType = oTestVm.sFirmwareType);
666 if oVM is None:
667 return False;
668
669 return True;
670
671 def _removeUnsupportedVirtModes(self, oTestDrv):
672 """
673 Removes unsupported virtualization modes.
674 """
675 if 'hwvirt' in self.asVirtModes and not oTestDrv.hasHostHwVirt():
676 reporter.log('Hardware assisted virtualization is not available on the host, skipping it.');
677 self.asVirtModes.remove('hwvirt');
678
679 if 'hwvirt-np' in self.asVirtModes and not oTestDrv.hasHostNestedPaging():
680 reporter.log('Nested paging not supported by the host, skipping it.');
681 self.asVirtModes.remove('hwvirt-np');
682
683 if 'raw' in self.asVirtModes and not oTestDrv.hasRawModeSupport():
684 reporter.log('Raw-mode virtualization is not available in this build (or perhaps for this host), skipping it.');
685 self.asVirtModes.remove('raw');
686
687 return True;
688
689 def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=R0914
690 """
691 For base.TestDriver.actionExecute. Calls the callback function for
692 each of the VMs and basic configuration variations (virt-mode and cpu
693 count).
694
695 Returns True if all fnCallback calls returned True, otherwise False.
696
697 The callback can return True, False or None. The latter is for when the
698 test is skipped. (True is for success, False is for failure.)
699 """
700
701 self._removeUnsupportedVirtModes(oTestDrv);
702 cMaxCpus = oTestDrv.getHostCpuCount();
703
704 #
705 # The test loop.
706 #
707 fRc = True;
708 for oTestVm in self.aoTestVms:
709 if oTestVm.fSkip and self.fIgnoreSkippedVm:
710 reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,));
711 continue;
712 reporter.testStart(oTestVm.sVmName);
713 if oTestVm.fSkip:
714 reporter.testDone(fSkipped = True);
715 continue;
716
717 # Intersect the supported modes and the ones being testing.
718 asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes];
719
720 # Ditto for CPUs.
721 acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus];
722
723 # Ditto for paravirtualization modes, except if not specified we got a less obvious default.
724 if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0:
725 asParavirtModes = [sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes];
726 assert None not in asParavirtModes;
727 elif oTestDrv.fpApiVer >= 5.0:
728 asParavirtModes = (oTestVm.asParavirtModesSup[0],);
729 assert asParavirtModes[0] is not None;
730 else:
731 asParavirtModes = (None,);
732
733 for cCpus in acCpusSup:
734 if cCpus == 1:
735 reporter.testStart('1 cpu');
736 else:
737 reporter.testStart('%u cpus' % (cCpus));
738 if cCpus > cMaxCpus:
739 reporter.testDone(fSkipped = True);
740 continue;
741
742 cTests = 0;
743 for sVirtMode in asVirtModesSup:
744 if sVirtMode == 'raw' and cCpus > 1:
745 continue;
746 reporter.testStart('%s' % ( g_dsVirtModeDescs[sVirtMode], ) );
747 cStartTests = cTests;
748
749 for sParavirtMode in asParavirtModes:
750 if sParavirtMode is not None:
751 assert oTestDrv.fpApiVer >= 5.0;
752 reporter.testStart('%s' % ( sParavirtMode, ) );
753
754 # Reconfigure the VM.
755 try:
756 (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode = sParavirtMode);
757 except KeyboardInterrupt:
758 raise;
759 except:
760 reporter.errorXcpt(cFrames = 9);
761 rc2 = False;
762 if rc2 is True:
763 # Do the testing.
764 try:
765 rc2 = fnCallback(oVM, oTestVm);
766 except KeyboardInterrupt:
767 raise;
768 except:
769 reporter.errorXcpt(cFrames = 9);
770 rc2 = False;
771 if rc2 is False:
772 reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed');
773 elif rc2 is False:
774 reporter.log('getReconfiguredVm failed');
775 if rc2 is False:
776 fRc = False;
777
778 cTests = cTests + (rc2 is not None);
779 if sParavirtMode is not None:
780 reporter.testDone(fSkipped = (rc2 is None));
781
782 reporter.testDone(fSkipped = cTests == cStartTests);
783
784 reporter.testDone(fSkipped = cTests == 0);
785
786 _, cErrors = reporter.testDone();
787 if cErrors > 0:
788 fRc = False;
789 return fRc;
790
791 def enumerateTestVms(self, fnCallback):
792 """
793 Enumerates all the 'active' VMs.
794
795 Returns True if all fnCallback calls returned True.
796 Returns False if any returned False.
797 Returns None immediately if fnCallback returned None.
798 """
799 fRc = True;
800 for oTestVm in self.aoTestVms:
801 if not oTestVm.fSkip:
802 fRc2 = fnCallback(oTestVm);
803 if fRc2 is None:
804 return fRc2;
805 fRc = fRc and fRc2;
806 return fRc;
807
808
809
810class TestVmManager(object):
811 """
812 Test VM manager.
813 """
814
815 def __init__(self, sResourcePath):
816 self.sResourcePath = sResourcePath;
817
818
819 def getStandardVmSet(self, sTxsTransport):
820 """
821 Gets the set of standard test VMs.
822
823 This is supposed to do something seriously clever, like searching the
824 testrsrc tree for usable VMs, but for the moment it's all hard coded. :-)
825 """
826
827 oSet = TestVmSet(oTestVmManager = self);
828
829 oTestVm = TestVm(oSet, 'tst-win10-efi', sHd = '4.2/efi/win10-efi-x86.vdi',
830 sKind = 'Windows10', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
831 oSet.aoTestVms.append(oTestVm);
832
833 oTestVm = TestVm(oSet, 'tst-win10-64-efi', sHd = '4.2/efi/win10-efi-amd64.vdi',
834 sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
835 oSet.aoTestVms.append(oTestVm);
836
837 oTestVm = TestVm(oSet, 'tst-ubuntu-15_10-64-efi', sHd = '4.2/efi/ubuntu-15_10-efi-amd64.vdi',
838 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
839 oSet.aoTestVms.append(oTestVm);
840
841 oTestVm = TestVm(oSet, 'tst-nt4sp1', sHd = '4.2/' + sTxsTransport + '/nt4sp1/t-nt4sp1.vdi',
842 sKind = 'WindowsNT4', acCpusSup = [1]);
843 oSet.aoTestVms.append(oTestVm);
844
845 oTestVm = TestVm(oSet, 'tst-xppro', sHd = '4.2/' + sTxsTransport + '/xppro/t-xppro.vdi',
846 sKind = 'WindowsXP', acCpusSup = range(1, 33));
847 oSet.aoTestVms.append(oTestVm);
848
849 oTestVm = TestVm(oSet, 'tst-nt4sp6', sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
850 sKind = 'WindowsNT4', acCpusSup = range(1, 33));
851 oSet.aoTestVms.append(oTestVm);
852
853 oTestVm = TestVm(oSet, 'tst-2ksp4', sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
854 sKind = 'Windows2000', acCpusSup = range(1, 33));
855 oSet.aoTestVms.append(oTestVm);
856
857 oTestVm = TestVm(oSet, 'tst-xpsp2', sHd = '4.2/xpsp2/t-winxpsp2.vdi',
858 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
859 oSet.aoTestVms.append(oTestVm);
860
861 oTestVm = TestVm(oSet, 'tst-xpsp2-halaacpi', sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
862 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
863 oSet.aoTestVms.append(oTestVm);
864
865 oTestVm = TestVm(oSet, 'tst-xpsp2-halacpi', sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
866 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
867 oSet.aoTestVms.append(oTestVm);
868
869 oTestVm = TestVm(oSet, 'tst-xpsp2-halapic', sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
870 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
871 oSet.aoTestVms.append(oTestVm);
872
873 oTestVm = TestVm(oSet, 'tst-xpsp2-halmacpi', sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
874 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
875 oSet.aoTestVms.append(oTestVm);
876
877 oTestVm = TestVm(oSet, 'tst-xpsp2-halmps', sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
878 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
879 oSet.aoTestVms.append(oTestVm);
880
881 oTestVm = TestVm(oSet, 'tst-win7', sHd = '4.2/win7-32/t-win7.vdi',
882 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True);
883 oSet.aoTestVms.append(oTestVm);
884
885 oTestVm = TestVm(oSet, 'tst-win8', sHd = '4.2/win8-32/t-win8.vdi',
886 sKind = 'Windows8', acCpusSup = range(1, 33), fIoApic = True);
887 oSet.aoTestVms.append(oTestVm);
888
889 return oSet;
890
891 def getSmokeVmSet(self):
892 """
893 Gets a representative set of VMs for smoke testing.
894 """
895
896 oSet = TestVmSet(oTestVmManager = self);
897
898 oTestVm = TestVm(oSet, 'tst-win10-efi', sHd = '4.2/efi/win10-efi-x86.vdi',
899 sKind = 'Windows10', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
900 oSet.aoTestVms.append(oTestVm);
901
902 oTestVm = TestVm(oSet, 'tst-win10-64-efi', sHd = '4.2/efi/win10-efi-amd64.vdi',
903 sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
904 oSet.aoTestVms.append(oTestVm);
905
906 oTestVm = TestVm(oSet, 'tst-ubuntu-15_10-64-efi', sHd = '4.2/efi/ubuntu-15_10-efi-amd64.vdi',
907 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
908 oSet.aoTestVms.append(oTestVm);
909
910 oTestVm = TestVm(oSet, 'tst-nt4sp1', sHd = '4.2/nat/nt4sp1/t-nt4sp1.vdi',
911 sKind = 'WindowsNT4', acCpusSup = [1], sNic0AttachType = 'nat');
912 oSet.aoTestVms.append(oTestVm);
913
914 oTestVm = TestVm(oSet, 'tst-xppro', sHd = '4.2/nat/xppro/t-xppro.vdi',
915 sKind = 'WindowsXP', acCpusSup = range(1, 33), sNic0AttachType = 'nat');
916 oSet.aoTestVms.append(oTestVm);
917
918 oTestVm = TestVm(oSet, 'tst-rhel5', sHd = '3.0/tcp/rhel5.vdi',
919 sKind = 'RedHat', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat');
920 oSet.aoTestVms.append(oTestVm);
921
922 oTestVm = TestVm(oSet, 'tst-win2k3ent', sHd = '3.0/tcp/win2k3ent-acpi.vdi',
923 sKind = 'Windows2003', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged');
924 oSet.aoTestVms.append(oTestVm);
925
926 oTestVm = TestVm(oSet, 'tst-sol10', sHd = '3.0/tcp/solaris10.vdi',
927 sKind = 'Solaris', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged');
928 oSet.aoTestVms.append(oTestVm);
929
930 oTestVm = TestVm(oSet, 'tst-sol10-64', sHd = '3.0/tcp/solaris10.vdi',
931 sKind = 'Solaris_64', acCpusSup = range(1, 33), sNic0AttachType = 'bridged');
932 oSet.aoTestVms.append(oTestVm);
933
934 oTestVm = TestVm(oSet, 'tst-sol11u1', sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
935 sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat',
936 fIoApic = True, sHddControllerType = 'SATA Controller');
937 oSet.aoTestVms.append(oTestVm);
938
939 oTestVm = TestVm(oSet, 'tst-nt4sp6', sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
940 sKind = 'WindowsNT4', acCpusSup = range(1, 33));
941 oSet.aoTestVms.append(oTestVm);
942
943 oTestVm = TestVm(oSet, 'tst-2ksp4', sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
944 sKind = 'Windows2000', acCpusSup = range(1, 33));
945 oSet.aoTestVms.append(oTestVm);
946
947 oTestVm = TestVm(oSet, 'tst-xpsp2', sHd = '4.2/xpsp2/t-winxpsp2.vdi',
948 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
949 oSet.aoTestVms.append(oTestVm);
950
951 oTestVm = TestVm(oSet, 'tst-xpsp2-halaacpi', sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
952 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
953 oSet.aoTestVms.append(oTestVm);
954
955 oTestVm = TestVm(oSet, 'tst-xpsp2-halacpi', sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
956 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
957 oSet.aoTestVms.append(oTestVm);
958
959 oTestVm = TestVm(oSet, 'tst-xpsp2-halapic', sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
960 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
961 oSet.aoTestVms.append(oTestVm);
962
963 oTestVm = TestVm(oSet, 'tst-xpsp2-halmacpi', sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
964 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
965 oSet.aoTestVms.append(oTestVm);
966
967 oTestVm = TestVm(oSet, 'tst-xpsp2-halmps', sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
968 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
969 oSet.aoTestVms.append(oTestVm);
970
971 oTestVm = TestVm(oSet, 'tst-win7', sHd = '4.2/win7-32/t-win7.vdi',
972 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True);
973 oSet.aoTestVms.append(oTestVm);
974
975 oTestVm = TestVm(oSet, 'tst-win8', sHd = '4.2/win8-32/t-win8.vdi',
976 sKind = 'Windows8', acCpusSup = range(1, 33), fIoApic = True);
977 oSet.aoTestVms.append(oTestVm);
978
979 return oSet;
980
981 def shutUpPyLint(self):
982 """ Shut up already! """
983 return self.sResourcePath;
984
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