VirtualBox

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

Last change on this file since 61950 was 61755, checked in by vboxsync, 8 years ago

Grr

  • 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 61755 2016-06-17 16:05:32Z 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: 61755 $"
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 if cCpus > 1:
326 fRc = fRc and oSession.enableIoApic(True);
327
328 if sParavirtMode is not None and oSession.fpApiVer >= 5.0:
329 adParavirtProviders = {
330 g_ksParavirtProviderNone : vboxcon.ParavirtProvider_None,
331 g_ksParavirtProviderDefault: vboxcon.ParavirtProvider_Default,
332 g_ksParavirtProviderLegacy : vboxcon.ParavirtProvider_Legacy,
333 g_ksParavirtProviderMinimal: vboxcon.ParavirtProvider_Minimal,
334 g_ksParavirtProviderHyperV : vboxcon.ParavirtProvider_HyperV,
335 g_ksParavirtProviderKVM : vboxcon.ParavirtProvider_KVM,
336 };
337 fRc = fRc and oSession.setParavirtProvider(adParavirtProviders[sParavirtMode]);
338
339 fCfg64Bit = self.is64bitRequired() or (self.is64bit() and fHostSupports64bit and sVirtMode != 'raw');
340 fRc = fRc and oSession.enableLongMode(fCfg64Bit);
341 if fCfg64Bit: # This is to avoid GUI pedantic warnings in the GUI. Sigh.
342 oOsType = oSession.getOsType();
343 if oOsType is not None:
344 if oOsType.is64Bit and sVirtMode == 'raw':
345 assert(oOsType.id[-3:] == '_64');
346 fRc = fRc and oSession.setOsType(oOsType.id[:-3]);
347 elif not oOsType.is64Bit and sVirtMode != 'raw':
348 fRc = fRc and oSession.setOsType(oOsType.id + '_64');
349
350 fRc = fRc and oSession.saveSettings();
351 if not oSession.close():
352 fRc = False;
353 if fRc is True:
354 return (True, oVM);
355 return (fRc, None);
356
357
358 def isWindows(self):
359 """ Checks if it's a Windows VM. """
360 return self.sGuestOsType == g_ksGuestOsTypeWindows;
361
362 def isOS2(self):
363 """ Checks if it's an OS/2 VM. """
364 return self.sGuestOsType == g_ksGuestOsTypeOS2;
365
366 def is64bit(self):
367 """ Checks if it's a 64-bit VM. """
368 return self.sKind.find('_64') >= 0;
369
370 def is64bitRequired(self):
371 """ Check if 64-bit is required or not. """
372 return (self.aInfo[g_iFlags] & g_k64) != 0;
373
374 def isLoggedOntoDesktop(self):
375 """ Checks if the test VM is logging onto a graphical desktop by default. """
376 if self.isWindows():
377 return True;
378 if self.isOS2():
379 return True;
380 if self.sVmName.find('-desktop'):
381 return True;
382 return False;
383
384 def isViaIncompatible(self):
385 """
386 Identifies VMs that doesn't work on VIA.
387
388 Returns True if NOT supported on VIA, False if it IS supported.
389 """
390 # Oracle linux doesn't like VIA in our experience
391 if self.aInfo[g_iKind] in ['Oracle', 'Oracle_64']:
392 return True;
393 # OS/2: "The system detected an internal processing error at location
394 # 0168:fff1da1f - 000e:ca1f. 0a8606fd
395 if self.isOS2():
396 return True;
397 # Windows NT4 before SP4 won't work because of cmpxchg8b not being
398 # detected, leading to a STOP 3e(80,0,0,0).
399 if self.aInfo[g_iKind] == 'WindowsNT4':
400 if self.sVmName.find('sp') < 0:
401 return True; # no service pack.
402 if self.sVmName.find('sp0') >= 0 \
403 or self.sVmName.find('sp1') >= 0 \
404 or self.sVmName.find('sp2') >= 0 \
405 or self.sVmName.find('sp3') >= 0:
406 return True;
407 return False;
408
409
410
411class BootSectorTestVm(TestVm):
412 """
413 A Boot Sector Test VM.
414 """
415
416 def __init__(self, oSet, sVmName, sFloppy = None, asVirtModesSup = None, f64BitRequired = False):
417 self.f64BitRequired = f64BitRequired;
418 if asVirtModesSup is None:
419 asVirtModesSup = list(g_asVirtModes);
420 TestVm.__init__(self, oSet, sVmName,
421 acCpusSup = [1,],
422 sFloppy = sFloppy,
423 asVirtModesSup = asVirtModesSup,
424 fPae = True,
425 fIoApic = True,
426 fVmmDevTestingPart = True,
427 fVmmDevTestingMmio = True,
428 );
429
430 def is64bitRequired(self):
431 return self.f64BitRequired;
432
433
434
435class TestVmSet(object):
436 """
437 A set of Test VMs.
438 """
439
440 def __init__(self, oTestVmManager = None, acCpus = None, asVirtModes = None, fIgnoreSkippedVm = False):
441 self.oTestVmManager = oTestVmManager;
442 if acCpus is None:
443 acCpus = [1, 2];
444 self.acCpusDef = acCpus;
445 self.acCpus = acCpus;
446 if asVirtModes is None:
447 asVirtModes = list(g_asVirtModes);
448 self.asVirtModesDef = asVirtModes;
449 self.asVirtModes = asVirtModes;
450 self.aoTestVms = [];
451 self.fIgnoreSkippedVm = fIgnoreSkippedVm;
452 self.asParavirtModes = None; ##< If None, use the first PV mode of the test VM, otherwise all modes in this list.
453
454 def findTestVmByName(self, sVmName):
455 """
456 Returns the TestVm object with the given name.
457 Returns None if not found.
458 """
459 for oTestVm in self.aoTestVms:
460 if oTestVm.sVmName == sVmName:
461 return oTestVm;
462 return None;
463
464 def getAllVmNames(self, sSep = ':'):
465 """
466 Returns names of all the test VMs in the set separated by
467 sSep (defaults to ':').
468 """
469 sVmNames = '';
470 for oTestVm in self.aoTestVms:
471 if sVmNames == '':
472 sVmNames = oTestVm.sVmName;
473 else:
474 sVmNames = sVmNames + sSep + oTestVm.sVmName;
475 return sVmNames;
476
477 def showUsage(self):
478 """
479 Invoked by vbox.TestDriver.
480 """
481 reporter.log('');
482 reporter.log('Test VM selection and general config options:');
483 reporter.log(' --virt-modes <m1[:m2[:]]');
484 reporter.log(' Default: %s' % (':'.join(self.asVirtModesDef)));
485 reporter.log(' --skip-virt-modes <m1[:m2[:]]');
486 reporter.log(' Use this to avoid hwvirt or hwvirt-np when not supported by the host');
487 reporter.log(' since we cannot detect it using the main API. Use after --virt-modes.');
488 reporter.log(' --cpu-counts <c1[:c2[:]]');
489 reporter.log(' Default: %s' % (':'.join(str(c) for c in self.acCpusDef)));
490 reporter.log(' --test-vms <vm1[:vm2[:...]]>');
491 reporter.log(' Test the specified VMs in the given order. Use this to change');
492 reporter.log(' the execution order or limit the choice of VMs');
493 reporter.log(' Default: %s (all)' % (self.getAllVmNames(),));
494 reporter.log(' --skip-vms <vm1[:vm2[:...]]>');
495 reporter.log(' Skip the specified VMs when testing.');
496 reporter.log(' --snapshot-restore-current');
497 reporter.log(' Restores the current snapshot and resumes execution.');
498 reporter.log(' --paravirt-modes <pv1[:pv2[:]]>');
499 reporter.log(' Set of paravirtualized providers (modes) to tests. Intersected with what the test VM supports.');
500 reporter.log(' Default is the first PV mode the test VMs support, generally same as "legacy".');
501 ## @todo Add more options for controlling individual VMs.
502 return True;
503
504 def parseOption(self, asArgs, iArg):
505 """
506 Parses the set test vm set options (--test-vms and --skip-vms), modifying the set
507 Invoked by the testdriver method with the same name.
508
509 Keyword arguments:
510 asArgs -- The argument vector.
511 iArg -- The index of the current argument.
512
513 Returns iArg if the option was not recognized and the caller should handle it.
514 Returns the index of the next argument when something is consumed.
515
516 In the event of a syntax error, a InvalidOption or QuietInvalidOption
517 is thrown.
518 """
519
520 if asArgs[iArg] == '--virt-modes':
521 iArg += 1;
522 if iArg >= len(asArgs):
523 raise base.InvalidOption('The "--virt-modes" takes a colon separated list of modes');
524
525 self.asVirtModes = asArgs[iArg].split(':');
526 for s in self.asVirtModes:
527 if s not in self.asVirtModesDef:
528 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
529 % (s, ' '.join(self.asVirtModesDef)));
530
531 elif asArgs[iArg] == '--skip-virt-modes':
532 iArg += 1;
533 if iArg >= len(asArgs):
534 raise base.InvalidOption('The "--skip-virt-modes" takes a colon separated list of modes');
535
536 for s in asArgs[iArg].split(':'):
537 if s not in self.asVirtModesDef:
538 raise base.InvalidOption('The "--virt-modes" value "%s" is not valid; valid values are: %s' \
539 % (s, ' '.join(self.asVirtModesDef)));
540 if s in self.asVirtModes:
541 self.asVirtModes.remove(s);
542
543 elif asArgs[iArg] == '--cpu-counts':
544 iArg += 1;
545 if iArg >= len(asArgs):
546 raise base.InvalidOption('The "--cpu-counts" takes a colon separated list of cpu counts');
547
548 self.acCpus = [];
549 for s in asArgs[iArg].split(':'):
550 try: c = int(s);
551 except: raise base.InvalidOption('The "--cpu-counts" value "%s" is not an integer' % (s,));
552 if c <= 0: raise base.InvalidOption('The "--cpu-counts" value "%s" is zero or negative' % (s,));
553 self.acCpus.append(c);
554
555 elif asArgs[iArg] == '--test-vms':
556 iArg += 1;
557 if iArg >= len(asArgs):
558 raise base.InvalidOption('The "--test-vms" takes colon separated list');
559
560 for oTestVm in self.aoTestVms:
561 oTestVm.fSkip = True;
562
563 asTestVMs = asArgs[iArg].split(':');
564 for s in asTestVMs:
565 oTestVm = self.findTestVmByName(s);
566 if oTestVm is None:
567 raise base.InvalidOption('The "--test-vms" value "%s" is not valid; valid values are: %s' \
568 % (s, self.getAllVmNames(' ')));
569 oTestVm.fSkip = False;
570
571 elif asArgs[iArg] == '--skip-vms':
572 iArg += 1;
573 if iArg >= len(asArgs):
574 raise base.InvalidOption('The "--skip-vms" takes colon separated list');
575
576 asTestVMs = asArgs[iArg].split(':');
577 for s in asTestVMs:
578 oTestVm = self.findTestVmByName(s);
579 if oTestVm is None:
580 reporter.log('warning: The "--test-vms" value "%s" does not specify any of our test VMs.' % (s,));
581 else:
582 oTestVm.fSkip = True;
583
584 elif asArgs[iArg] == '--snapshot-restore-current':
585 for oTestVm in self.aoTestVms:
586 if oTestVm.fSkip is False:
587 oTestVm.fSnapshotRestoreCurrent = True;
588 reporter.log('VM "%s" will be restored.' % (oTestVm.sVmName));
589
590 elif asArgs[iArg] == '--paravirt-modes':
591 iArg += 1
592 if iArg >= len(asArgs):
593 raise base.InvalidOption('The "--paravirt-modes" takes a colon separated list of modes');
594
595 self.asParavirtModes = asArgs[iArg].split(':')
596 for sPvMode in self.asParavirtModes:
597 if sPvMode not in g_kasParavirtProviders:
598 raise base.InvalidOption('The "--paravirt-modes" value "%s" is not valid; valid values are: %s'
599 % (sPvMode, ', '.join(g_kasParavirtProviders),));
600 if len(self.asParavirtModes) == 0:
601 self.asParavirtModes = None;
602
603 else:
604 return iArg;
605 return iArg + 1;
606
607 def getResourceSet(self):
608 """
609 Implements base.TestDriver.getResourceSet
610 """
611 asResources = [];
612 for oTestVm in self.aoTestVms:
613 if not oTestVm.fSkip:
614 if oTestVm.sHd is not None:
615 asResources.append(oTestVm.sHd);
616 if oTestVm.sDvdImage is not None:
617 asResources.append(oTestVm.sDvdImage);
618 return asResources;
619
620 def actionConfig(self, oTestDrv, eNic0AttachType = None, sDvdImage = None):
621 """
622 For base.TestDriver.actionConfig. Configure the VMs with defaults and
623 a few tweaks as per arguments.
624
625 Returns True if successful.
626 Returns False if not.
627 """
628
629 for oTestVm in self.aoTestVms:
630 if oTestVm.fSkip:
631 continue;
632
633 if oTestVm.fSnapshotRestoreCurrent:
634 # If we want to restore a VM we don't need to create
635 # the machine anymore -- so just add it to the test VM list.
636 oVM = oTestDrv.addTestMachine(oTestVm.sVmName);
637 else:
638 ## @todo This could possibly be moved to the TestVM object.
639 if sDvdImage is not None:
640 sMyDvdImage = sDvdImage;
641 else:
642 sMyDvdImage = oTestVm.sDvdImage;
643
644 if eNic0AttachType is not None:
645 eMyNic0AttachType = eNic0AttachType;
646 elif oTestVm.sNic0AttachType is None:
647 eMyNic0AttachType = None;
648 elif oTestVm.sNic0AttachType == 'nat':
649 eMyNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
650 elif oTestVm.sNic0AttachType == 'bridged':
651 eMyNic0AttachType = vboxcon.NetworkAttachmentType_Bridged;
652 else:
653 assert False, oTestVm.sNic0AttachType;
654
655 oVM = oTestDrv.createTestVM(oTestVm.sVmName, 1, \
656 sHd = oTestVm.sHd, \
657 sKind = oTestVm.sKind, \
658 fIoApic = oTestVm.fIoApic, \
659 fPae = oTestVm.fPae, \
660 eNic0AttachType = eMyNic0AttachType, \
661 sDvdImage = sMyDvdImage, \
662 sHddControllerType = oTestVm.sHddControllerType,
663 sFloppy = oTestVm.sFloppy,
664 fVmmDevTestingPart = oTestVm.fVmmDevTestingPart,
665 fVmmDevTestingMmio = oTestVm.fVmmDevTestingPart,
666 sFirmwareType = oTestVm.sFirmwareType);
667 if oVM is None:
668 return False;
669
670 return True;
671
672 def _removeUnsupportedVirtModes(self, oTestDrv):
673 """
674 Removes unsupported virtualization modes.
675 """
676 if 'hwvirt' in self.asVirtModes and not oTestDrv.hasHostHwVirt():
677 reporter.log('Hardware assisted virtualization is not available on the host, skipping it.');
678 self.asVirtModes.remove('hwvirt');
679
680 if 'hwvirt-np' in self.asVirtModes and not oTestDrv.hasHostNestedPaging():
681 reporter.log('Nested paging not supported by the host, skipping it.');
682 self.asVirtModes.remove('hwvirt-np');
683
684 if 'raw' in self.asVirtModes and not oTestDrv.hasRawModeSupport():
685 reporter.log('Raw-mode virtualization is not available in this build (or perhaps for this host), skipping it.');
686 self.asVirtModes.remove('raw');
687
688 return True;
689
690 def actionExecute(self, oTestDrv, fnCallback): # pylint: disable=R0914
691 """
692 For base.TestDriver.actionExecute. Calls the callback function for
693 each of the VMs and basic configuration variations (virt-mode and cpu
694 count).
695
696 Returns True if all fnCallback calls returned True, otherwise False.
697
698 The callback can return True, False or None. The latter is for when the
699 test is skipped. (True is for success, False is for failure.)
700 """
701
702 self._removeUnsupportedVirtModes(oTestDrv);
703 cMaxCpus = oTestDrv.getHostCpuCount();
704
705 #
706 # The test loop.
707 #
708 fRc = True;
709 for oTestVm in self.aoTestVms:
710 if oTestVm.fSkip and self.fIgnoreSkippedVm:
711 reporter.log2('Ignoring VM %s (fSkip = True).' % (oTestVm.sVmName,));
712 continue;
713 reporter.testStart(oTestVm.sVmName);
714 if oTestVm.fSkip:
715 reporter.testDone(fSkipped = True);
716 continue;
717
718 # Intersect the supported modes and the ones being testing.
719 asVirtModesSup = [sMode for sMode in oTestVm.asVirtModesSup if sMode in self.asVirtModes];
720
721 # Ditto for CPUs.
722 acCpusSup = [cCpus for cCpus in oTestVm.acCpusSup if cCpus in self.acCpus];
723
724 # Ditto for paravirtualization modes, except if not specified we got a less obvious default.
725 if self.asParavirtModes is not None and oTestDrv.fpApiVer >= 5.0:
726 asParavirtModes = [sPvMode for sPvMode in oTestVm.asParavirtModesSup if sPvMode in self.asParavirtModes];
727 assert None not in asParavirtModes;
728 elif oTestDrv.fpApiVer >= 5.0:
729 asParavirtModes = (oTestVm.asParavirtModesSup[0],);
730 assert asParavirtModes[0] is not None;
731 else:
732 asParavirtModes = (None,);
733
734 for cCpus in acCpusSup:
735 if cCpus == 1:
736 reporter.testStart('1 cpu');
737 else:
738 reporter.testStart('%u cpus' % (cCpus));
739 if cCpus > cMaxCpus:
740 reporter.testDone(fSkipped = True);
741 continue;
742
743 cTests = 0;
744 for sVirtMode in asVirtModesSup:
745 if sVirtMode == 'raw' and cCpus > 1:
746 continue;
747 reporter.testStart('%s' % ( g_dsVirtModeDescs[sVirtMode], ) );
748 cStartTests = cTests;
749
750 for sParavirtMode in asParavirtModes:
751 if sParavirtMode is not None:
752 assert oTestDrv.fpApiVer >= 5.0;
753 reporter.testStart('%s' % ( sParavirtMode, ) );
754
755 # Reconfigure the VM.
756 try:
757 (rc2, oVM) = oTestVm.getReconfiguredVm(oTestDrv, cCpus, sVirtMode, sParavirtMode = sParavirtMode);
758 except KeyboardInterrupt:
759 raise;
760 except:
761 reporter.errorXcpt(cFrames = 9);
762 rc2 = False;
763 if rc2 is True:
764 # Do the testing.
765 try:
766 rc2 = fnCallback(oVM, oTestVm);
767 except KeyboardInterrupt:
768 raise;
769 except:
770 reporter.errorXcpt(cFrames = 9);
771 rc2 = False;
772 if rc2 is False:
773 reporter.maybeErr(reporter.testErrorCount() == 0, 'fnCallback failed');
774 elif rc2 is False:
775 reporter.log('getReconfiguredVm failed');
776 if rc2 is False:
777 fRc = False;
778
779 cTests = cTests + (rc2 is not None);
780 if sParavirtMode is not None:
781 reporter.testDone(fSkipped = (rc2 is None));
782
783 reporter.testDone(fSkipped = cTests == cStartTests);
784
785 reporter.testDone(fSkipped = cTests == 0);
786
787 _, cErrors = reporter.testDone();
788 if cErrors > 0:
789 fRc = False;
790 return fRc;
791
792 def enumerateTestVms(self, fnCallback):
793 """
794 Enumerates all the 'active' VMs.
795
796 Returns True if all fnCallback calls returned True.
797 Returns False if any returned False.
798 Returns None immediately if fnCallback returned None.
799 """
800 fRc = True;
801 for oTestVm in self.aoTestVms:
802 if not oTestVm.fSkip:
803 fRc2 = fnCallback(oTestVm);
804 if fRc2 is None:
805 return fRc2;
806 fRc = fRc and fRc2;
807 return fRc;
808
809
810
811class TestVmManager(object):
812 """
813 Test VM manager.
814 """
815
816 def __init__(self, sResourcePath):
817 self.sResourcePath = sResourcePath;
818
819
820 def getStandardVmSet(self, sTxsTransport):
821 """
822 Gets the set of standard test VMs.
823
824 This is supposed to do something seriously clever, like searching the
825 testrsrc tree for usable VMs, but for the moment it's all hard coded. :-)
826 """
827
828 oSet = TestVmSet(oTestVmManager = self);
829
830 oTestVm = TestVm(oSet, 'tst-win10-efi', sHd = '4.2/efi/win10-efi-x86.vdi',
831 sKind = 'Windows10', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
832 oSet.aoTestVms.append(oTestVm);
833
834 oTestVm = TestVm(oSet, 'tst-win10-64-efi', sHd = '4.2/efi/win10-efi-amd64.vdi',
835 sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
836 oSet.aoTestVms.append(oTestVm);
837
838 oTestVm = TestVm(oSet, 'tst-ubuntu-15_10-64-efi', sHd = '4.2/efi/ubuntu-15_10-efi-amd64.vdi',
839 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
840 oSet.aoTestVms.append(oTestVm);
841
842 oTestVm = TestVm(oSet, 'tst-nt4sp1', sHd = '4.2/' + sTxsTransport + '/nt4sp1/t-nt4sp1.vdi',
843 sKind = 'WindowsNT4', acCpusSup = [1]);
844 oSet.aoTestVms.append(oTestVm);
845
846 oTestVm = TestVm(oSet, 'tst-xppro', sHd = '4.2/' + sTxsTransport + '/xppro/t-xppro.vdi',
847 sKind = 'WindowsXP', acCpusSup = range(1, 33));
848 oSet.aoTestVms.append(oTestVm);
849
850 oTestVm = TestVm(oSet, 'tst-nt4sp6', sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
851 sKind = 'WindowsNT4', acCpusSup = range(1, 33));
852 oSet.aoTestVms.append(oTestVm);
853
854 oTestVm = TestVm(oSet, 'tst-2ksp4', sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
855 sKind = 'Windows2000', acCpusSup = range(1, 33));
856 oSet.aoTestVms.append(oTestVm);
857
858 oTestVm = TestVm(oSet, 'tst-xpsp2', sHd = '4.2/xpsp2/t-winxpsp2.vdi',
859 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
860 oSet.aoTestVms.append(oTestVm);
861
862 oTestVm = TestVm(oSet, 'tst-xpsp2-halaacpi', sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
863 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
864 oSet.aoTestVms.append(oTestVm);
865
866 oTestVm = TestVm(oSet, 'tst-xpsp2-halacpi', sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
867 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
868 oSet.aoTestVms.append(oTestVm);
869
870 oTestVm = TestVm(oSet, 'tst-xpsp2-halapic', sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
871 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
872 oSet.aoTestVms.append(oTestVm);
873
874 oTestVm = TestVm(oSet, 'tst-xpsp2-halmacpi', sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
875 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
876 oSet.aoTestVms.append(oTestVm);
877
878 oTestVm = TestVm(oSet, 'tst-xpsp2-halmps', sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
879 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
880 oSet.aoTestVms.append(oTestVm);
881
882 oTestVm = TestVm(oSet, 'tst-win7', sHd = '4.2/win7-32/t-win7.vdi',
883 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True);
884 oSet.aoTestVms.append(oTestVm);
885
886 oTestVm = TestVm(oSet, 'tst-win8', sHd = '4.2/win8-32/t-win8.vdi',
887 sKind = 'Windows8', acCpusSup = range(1, 33), fIoApic = True);
888 oSet.aoTestVms.append(oTestVm);
889
890 return oSet;
891
892 def getSmokeVmSet(self):
893 """
894 Gets a representative set of VMs for smoke testing.
895 """
896
897 oSet = TestVmSet(oTestVmManager = self);
898
899 oTestVm = TestVm(oSet, 'tst-win10-efi', sHd = '4.2/efi/win10-efi-x86.vdi',
900 sKind = 'Windows10', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
901 oSet.aoTestVms.append(oTestVm);
902
903 oTestVm = TestVm(oSet, 'tst-win10-64-efi', sHd = '4.2/efi/win10-efi-amd64.vdi',
904 sKind = 'Windows10_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
905 oSet.aoTestVms.append(oTestVm);
906
907 oTestVm = TestVm(oSet, 'tst-ubuntu-15_10-64-efi', sHd = '4.2/efi/ubuntu-15_10-efi-amd64.vdi',
908 sKind = 'Ubuntu_64', acCpusSup = range(1, 33), fIoApic = True, sFirmwareType = 'efi');
909 oSet.aoTestVms.append(oTestVm);
910
911 oTestVm = TestVm(oSet, 'tst-nt4sp1', sHd = '4.2/nat/nt4sp1/t-nt4sp1.vdi',
912 sKind = 'WindowsNT4', acCpusSup = [1], sNic0AttachType = 'nat');
913 oSet.aoTestVms.append(oTestVm);
914
915 oTestVm = TestVm(oSet, 'tst-xppro', sHd = '4.2/nat/xppro/t-xppro.vdi',
916 sKind = 'WindowsXP', acCpusSup = range(1, 33), sNic0AttachType = 'nat');
917 oSet.aoTestVms.append(oTestVm);
918
919 oTestVm = TestVm(oSet, 'tst-rhel5', sHd = '3.0/tcp/rhel5.vdi',
920 sKind = 'RedHat', acCpusSup = range(1, 33), fIoApic = True, sNic0AttachType = 'nat');
921 oSet.aoTestVms.append(oTestVm);
922
923 oTestVm = TestVm(oSet, 'tst-win2k3ent', sHd = '3.0/tcp/win2k3ent-acpi.vdi',
924 sKind = 'Windows2003', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged');
925 oSet.aoTestVms.append(oTestVm);
926
927 oTestVm = TestVm(oSet, 'tst-sol10', sHd = '3.0/tcp/solaris10.vdi',
928 sKind = 'Solaris', acCpusSup = range(1, 33), fPae = True, sNic0AttachType = 'bridged');
929 oSet.aoTestVms.append(oTestVm);
930
931 oTestVm = TestVm(oSet, 'tst-sol10-64', sHd = '3.0/tcp/solaris10.vdi',
932 sKind = 'Solaris_64', acCpusSup = range(1, 33), sNic0AttachType = 'bridged');
933 oSet.aoTestVms.append(oTestVm);
934
935 oTestVm = TestVm(oSet, 'tst-sol11u1', sHd = '4.2/nat/sol11u1/t-sol11u1.vdi',
936 sKind = 'Solaris11_64', acCpusSup = range(1, 33), sNic0AttachType = 'nat',
937 fIoApic = True, sHddControllerType = 'SATA Controller');
938 oSet.aoTestVms.append(oTestVm);
939
940 oTestVm = TestVm(oSet, 'tst-nt4sp6', sHd = '4.2/nt4sp6/t-nt4sp6.vdi',
941 sKind = 'WindowsNT4', acCpusSup = range(1, 33));
942 oSet.aoTestVms.append(oTestVm);
943
944 oTestVm = TestVm(oSet, 'tst-2ksp4', sHd = '4.2/win2ksp4/t-win2ksp4.vdi',
945 sKind = 'Windows2000', acCpusSup = range(1, 33));
946 oSet.aoTestVms.append(oTestVm);
947
948 oTestVm = TestVm(oSet, 'tst-xpsp2', sHd = '4.2/xpsp2/t-winxpsp2.vdi',
949 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
950 oSet.aoTestVms.append(oTestVm);
951
952 oTestVm = TestVm(oSet, 'tst-xpsp2-halaacpi', sHd = '4.2/xpsp2/t-winxp-halaacpi.vdi',
953 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
954 oSet.aoTestVms.append(oTestVm);
955
956 oTestVm = TestVm(oSet, 'tst-xpsp2-halacpi', sHd = '4.2/xpsp2/t-winxp-halacpi.vdi',
957 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
958 oSet.aoTestVms.append(oTestVm);
959
960 oTestVm = TestVm(oSet, 'tst-xpsp2-halapic', sHd = '4.2/xpsp2/t-winxp-halapic.vdi',
961 sKind = 'WindowsXP', acCpusSup = range(1, 33), fIoApic = True);
962 oSet.aoTestVms.append(oTestVm);
963
964 oTestVm = TestVm(oSet, 'tst-xpsp2-halmacpi', sHd = '4.2/xpsp2/t-winxp-halmacpi.vdi',
965 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
966 oSet.aoTestVms.append(oTestVm);
967
968 oTestVm = TestVm(oSet, 'tst-xpsp2-halmps', sHd = '4.2/xpsp2/t-winxp-halmps.vdi',
969 sKind = 'WindowsXP', acCpusSup = range(2, 33), fIoApic = True);
970 oSet.aoTestVms.append(oTestVm);
971
972 oTestVm = TestVm(oSet, 'tst-win7', sHd = '4.2/win7-32/t-win7.vdi',
973 sKind = 'Windows7', acCpusSup = range(1, 33), fIoApic = True);
974 oSet.aoTestVms.append(oTestVm);
975
976 oTestVm = TestVm(oSet, 'tst-win8', sHd = '4.2/win8-32/t-win8.vdi',
977 sKind = 'Windows8', acCpusSup = range(1, 33), fIoApic = True);
978 oSet.aoTestVms.append(oTestVm);
979
980 return oSet;
981
982 def shutUpPyLint(self):
983 """ Shut up already! """
984 return self.sResourcePath;
985
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