VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/tests/additions/tdAddBasic1.py@ 78644

Last change on this file since 78644 was 78644, checked in by vboxsync, 6 years ago

tdAddSharedFolders1.py: Shared folder testing is halfways working now... bugref:9172

  • Property svn:eol-style set to LF
  • Property svn:executable set to *
  • Property svn:keywords set to Author Date Id Revision
File size: 17.6 KB
Line 
1#!/usr/bin/env python
2# -*- coding: utf-8 -*-
3# $Id: tdAddBasic1.py 78644 2019-05-22 00:29:14Z vboxsync $
4
5"""
6VirtualBox Validation Kit - Additions Basics #1.
7"""
8
9__copyright__ = \
10"""
11Copyright (C) 2010-2019 Oracle Corporation
12
13This file is part of VirtualBox Open Source Edition (OSE), as
14available from http://www.virtualbox.org. This file is free software;
15you can redistribute it and/or modify it under the terms of the GNU
16General Public License (GPL) as published by the Free Software
17Foundation, in version 2 as it comes in the "COPYING" file of the
18VirtualBox OSE distribution. VirtualBox OSE is distributed in the
19hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
20
21The contents of this file may alternatively be used under the terms
22of the Common Development and Distribution License Version 1.0
23(CDDL) only, as it comes in the "COPYING.CDDL" file of the
24VirtualBox OSE distribution, in which case the provisions of the
25CDDL are applicable instead of those of the GPL.
26
27You may elect to license modified versions of this file under the
28terms and conditions of either the GPL or the CDDL or both.
29"""
30__version__ = "$Revision: 78644 $"
31
32# pylint: disable=unnecessary-semicolon
33
34# Standard Python imports.
35import os;
36import sys;
37import uuid;
38
39# Only the main script needs to modify the path.
40try: __file__
41except: __file__ = sys.argv[0];
42g_ksValidationKitDir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))));
43sys.path.append(g_ksValidationKitDir);
44
45# Validation Kit imports.
46from testdriver import reporter;
47from testdriver import base;
48from testdriver import vbox;
49from testdriver import vboxcon;
50
51# Sub test driver imports.
52sys.path.append(os.path.dirname(os.path.abspath(__file__))); # For sub-test drivers.
53from tdAddGuestCtrl import SubTstDrvAddGuestCtrl;
54from tdAddSharedFolders1 import SubTstDrvAddSharedFolders1;
55
56
57class tdAddBasic1(vbox.TestDriver): # pylint: disable=R0902
58 """
59 Additions Basics #1.
60 """
61 ## @todo
62 # - More of the settings stuff can be and need to be generalized!
63 #
64
65 def __init__(self):
66 vbox.TestDriver.__init__(self);
67 self.oTestVmSet = self.oTestVmManager.getSmokeVmSet('nat');
68 self.asTestsDef = ['install', 'guestprops', 'stdguestprops', 'guestcontrol', ]; #'sharedfolders'];
69 self.asTests = self.asTestsDef;
70 self.asRsrcs = None
71
72 self.addSubTestDriver(SubTstDrvAddGuestCtrl(self));
73 self.addSubTestDriver(SubTstDrvAddSharedFolders1(self));
74
75 #
76 # Overridden methods.
77 #
78 def showUsage(self):
79 rc = vbox.TestDriver.showUsage(self);
80 reporter.log('');
81 reporter.log('tdAddBasic1 Options:');
82 reporter.log(' --tests <s1[:s2[:]]>');
83 reporter.log(' Default: %s (all)' % (':'.join(self.asTestsDef)));
84 reporter.log(' --quick');
85 reporter.log(' Same as --virt-modes hwvirt --cpu-counts 1.');
86 return rc;
87
88 def parseOption(self, asArgs, iArg): # pylint: disable=R0912,R0915
89 if asArgs[iArg] == '--tests':
90 iArg += 1;
91 if iArg >= len(asArgs): raise base.InvalidOption('The "--tests" takes a colon separated list of tests');
92 self.asTests = asArgs[iArg].split(':');
93 for s in self.asTests:
94 if s not in self.asTestsDef:
95 raise base.InvalidOption('The "--tests" value "%s" is not valid; valid values are: %s'
96 % (s, ' '.join(self.asTestsDef),));
97
98 elif asArgs[iArg] == '--quick':
99 self.parseOption(['--virt-modes', 'hwvirt'], 0);
100 self.parseOption(['--cpu-counts', '1'], 0);
101
102 else:
103 return vbox.TestDriver.parseOption(self, asArgs, iArg);
104 return iArg + 1;
105
106 def getResourceSet(self):
107 if self.asRsrcs is None:
108 self.asRsrcs = []
109 for oSubTstDrv in self.aoSubTstDrvs:
110 self.asRsrcs.extend(oSubTstDrv.asRsrcs)
111 self.asRsrcs.extend(self.oTestVmSet.getResourceSet())
112 return self.asRsrcs
113
114 def actionConfig(self):
115 if not self.importVBoxApi(): # So we can use the constant below.
116 return False;
117
118 eNic0AttachType = vboxcon.NetworkAttachmentType_NAT;
119 sGaIso = self.getGuestAdditionsIso();
120
121 # On 6.0 we merge the GAs with the ValidationKit so we can get at FsPerf.
122 # Note! Not possible to do a dboule import as both images an '/OS2' dir.
123 # So, using same dir as with unattended VISOs for the valkit.
124 if self.fpApiVer >= 6.0 and 'sharedfolders' in self.asTests:
125 sGaViso = os.path.join(self.sScratchPath, 'AdditionsAndValKit.viso');
126 ## @todo encode as bash cmd line:
127 sVisoContent = '--iprt-iso-maker-file-marker-bourne-sh %s ' \
128 '--import-iso \'%s\' ' \
129 '--push-iso \'%s\' ' \
130 '/vboxvalidationkit=/ ' \
131 '--pop ' \
132 % (uuid.uuid4(), sGaIso, self.sVBoxValidationKitIso);
133 reporter.log2('Using VISO combining GAs and ValKit "%s": %s' % (sGaViso, sVisoContent));
134 oGaViso = open(sGaViso, 'w');
135 oGaViso.write(sVisoContent);
136 oGaViso.close();
137 sGaIso = sGaViso;
138
139 return self.oTestVmSet.actionConfig(self, eNic0AttachType = eNic0AttachType, sDvdImage = sGaIso);
140
141 def actionExecute(self):
142 return self.oTestVmSet.actionExecute(self, self.testOneCfg);
143
144
145 #
146 # Test execution helpers.
147 #
148
149 def testOneCfg(self, oVM, oTestVm):
150 """
151 Runs the specified VM thru the tests.
152
153 Returns a success indicator on the general test execution. This is not
154 the actual test result.
155 """
156 fRc = False;
157
158 if oTestVm.isWindows():
159 sFileCdWait = 'VBoxWindowsAdditions.exe';
160 elif oTestVm.isLinux():
161 sFileCdWait = 'VBoxLinuxAdditions.run';
162
163 self.logVmInfo(oVM);
164 oSession, oTxsSession = self.startVmAndConnectToTxsViaTcp(oTestVm.sVmName, fCdWait = True, sFileCdWait = sFileCdWait);
165 if oSession is not None:
166 self.addTask(oTxsSession);
167 # Do the testing.
168 fSkip = 'install' not in self.asTests;
169 reporter.testStart('Install');
170 if not fSkip:
171 fRc, oTxsSession = self.testInstallAdditions(oSession, oTxsSession, oTestVm);
172 reporter.testDone(fSkip);
173
174 fSkip = 'guestprops' not in self.asTests;
175 reporter.testStart('Guest Properties');
176 if not fSkip:
177 fRc = self.testGuestProperties(oSession, oTxsSession, oTestVm) and fRc;
178 reporter.testDone(fSkip);
179
180 fSkip = 'guestcontrol' not in self.asTests;
181 reporter.testStart('Guest Control');
182 if not fSkip:
183 fRc, oTxsSession = self.aoSubTstDrvs[0].testIt(oTestVm, oSession, oTxsSession);
184 reporter.testDone(fSkip);
185
186 fSkip = 'sharedfolders' not in self.asTests and self.fpApiVer >= 6.0;
187 reporter.testStart('Shared Folders');
188 if not fSkip:
189 fRc, oTxsSession = self.aoSubTstDrvs[1].testIt(oTestVm, oSession, oTxsSession);
190 reporter.testDone(fSkip or fRc is None);
191
192 ## @todo Save and restore test.
193
194 ## @todo Reset tests.
195
196 ## @todo Final test: Uninstallation.
197
198 # Cleanup.
199 self.removeTask(oTxsSession);
200 self.terminateVmBySession(oSession)
201 return fRc;
202
203 def testInstallAdditions(self, oSession, oTxsSession, oTestVm):
204 """
205 Tests installing the guest additions
206 """
207 if oTestVm.isWindows():
208 (fRc, oTxsSession) = self.testWindowsInstallAdditions(oSession, oTxsSession, oTestVm);
209 elif oTestVm.isLinux():
210 (fRc, oTxsSession) = self.testLinuxInstallAdditions(oSession, oTxsSession, oTestVm);
211 else:
212 reporter.error('Guest Additions installation not implemented for %s yet! (%s)' % \
213 (oTestVm.sKind, oTestVm.sVmName,));
214 fRc = False;
215
216 #
217 # Verify installation of Guest Additions using commmon bits.
218 #
219 if fRc is True:
220 #
221 # Wait for the GAs to come up.
222 #
223
224 ## @todo need to signed up for a OnAdditionsStateChanged and wait runlevel to
225 # at least reach Userland.
226
227 #
228 # Check if the additions are operational.
229 #
230 try: oGuest = oSession.o.console.guest;
231 except:
232 reporter.errorXcpt('Getting IGuest failed.');
233 return (False, oTxsSession);
234
235 # Check the additionsVersion attribute. It must not be empty.
236 reporter.testStart('IGuest::additionsVersion');
237 fRc = self.testIGuest_additionsVersion(oGuest);
238 reporter.testDone();
239
240 reporter.testStart('IGuest::additionsRunLevel');
241 self.testIGuest_additionsRunLevel(oGuest, oTestVm);
242 reporter.testDone();
243
244 ## @todo test IAdditionsFacilities.
245
246 return (fRc, oTxsSession);
247
248 def testWindowsInstallAdditions(self, oSession, oTxsSession, oTestVm):
249 """
250 Installs the Windows guest additions using the test execution service.
251 Since this involves rebooting the guest, we will have to create a new TXS session.
252 """
253 asLogFiles = [];
254
255 fHaveSetupApiDevLog = False;
256
257 # Delete relevant log files.
258 if oTestVm.sKind in ('WindowsNT4',):
259 sWinDir = 'C:/WinNT/';
260 else:
261 sWinDir = 'C:/Windows/';
262 asLogFiles = [sWinDir + 'setupapi.log', sWinDir + 'setupact.log', sWinDir + 'setuperr.log'];
263
264 # Apply The SetupAPI logging level so that we also get the (most verbose) setupapi.dev.log file.
265 ## @todo !!! HACK ALERT !!! Add the value directly into the testing source image. Later.
266 fHaveSetupApiDevLog = self.txsRunTest(oTxsSession, 'Enabling setupapi.dev.log', 30 * 1000,
267 'c:\\Windows\\System32\\reg.exe',
268 ('c:\\Windows\\System32\\reg.exe', 'add',
269 '"HKLM\\Software\\Microsoft\\Windows\\CurrentVersion\\Setup"',
270 '/v', 'LogLevel', '/t', 'REG_DWORD', '/d', '0xFF'));
271
272 # On some guests the files in question still can be locked by the OS, so ignore deletion
273 # errors from the guest side (e.g. sharing violations) and just continue.
274 for sFile in asLogFiles:
275 self.txsRmFile(oSession, oTxsSession, sFile, 10 * 1000, fIgnoreErrors = True);
276
277 # Install the public signing key.
278 if oTestVm.sKind not in ('WindowsNT4', 'Windows2000', 'WindowsXP', 'Windows2003'):
279 ## TODO
280 pass;
281
282 #
283 # The actual install.
284 # Enable installing the optional auto-logon modules (VBoxGINA/VBoxCredProv) + (Direct)3D support.
285 # Also tell the installer to produce the appropriate log files.
286 #
287 fRc = self.txsRunTest(oTxsSession, 'VBoxWindowsAdditions.exe', 5 * 60 * 1000, '${CDROM}/VBoxWindowsAdditions.exe',
288 ('${CDROM}/VBoxWindowsAdditions.exe', '/S', '/l', '/with_autologon'));
289 ## @todo For testing the installation (D)3D stuff ('/with_d3d') we need to boot up in safe mode.
290
291 #
292 # Reboot the VM and reconnect the TXS session.
293 #
294 if fRc is True:
295 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 3 * 60000);
296
297 if fRc is True:
298 # Add the Windows Guest Additions installer files to the files we want to download
299 # from the guest.
300 sGuestAddsDir = 'C:/Program Files/Oracle/VirtualBox Guest Additions/';
301 asLogFiles.append(sGuestAddsDir + 'install.log');
302 # Note: There won't be a install_ui.log because of the silent installation.
303 asLogFiles.append(sGuestAddsDir + 'install_drivers.log');
304 asLogFiles.append('C:/Windows/setupapi.log');
305
306 # Note: setupapi.dev.log only is available since Windows 2000.
307 if fHaveSetupApiDevLog:
308 asLogFiles.append('C:/Windows/setupapi.dev.log');
309
310 #
311 # Download log files.
312 # Ignore errors as all files above might not be present (or in different locations)
313 # on different Windows guests.
314 #
315 self.txsDownloadFiles(oSession, oTxsSession, asLogFiles, fIgnoreErrors = True);
316
317 return (fRc, oTxsSession);
318
319 def testLinuxInstallAdditions(self, oSession, oTxsSession, oTestVm):
320 oSession = oSession;
321 oTestVm = oTestVm;
322
323 fRc = False;
324
325 # Install Kernel headers, which are required for actually installing the Linux Additions.
326 if oTestVm.sKind.startswith('Debian') \
327 or oTestVm.sKind.startswith('Ubuntu'):
328 fRc = self.txsRunTest(oTxsSession, 'Installing Kernel headers', 5 * 60 *1000,
329 '/usr/bin/apt-get', ('/usr/bin/apt-get', 'install', '-y', 'linux-headers-generic'));
330 if not fRc:
331 reporter.error('Error installing Kernel headers');
332 fRc = self.txsRunTest(oTxsSession, 'Installing Guest Additions depdendencies', 5 * 60 *1000, \
333 '/usr/bin/apt-get', ('/usr/bin/apt-get', 'install', '-y', 'build-essential', 'perl'));
334 if not fRc:
335 reporter.error('Error installing additional installer dependencies');
336 elif oTestVm.sKind.startswith('OL') \
337 or oTestVm.sKind.startswith('Oracle') \
338 or oTestVm.sKind.startswith('RHEL') \
339 or oTestVm.sKind.startswith('Redhat') \
340 or oTestVm.sKind.startswith('Cent'):
341 fRc = self.txsRunTest(oTxsSession, 'Installing Kernel headers', 5 * 60 *1000,
342 '/usr/bin/yum', ('/usr/bin/yum', '-y', 'install', 'kernel-headers'));
343 if not fRc:
344 reporter.error('Error installing Kernel headers');
345 fRc = self.txsRunTest(oTxsSession, 'Installing Guest Additions depdendencies', 5 * 60 *1000, \
346 '/usr/bin/yum', ('/usr/bin/yum', '-y', 'install', \
347 'make', 'automake', 'gcc', 'kernel-devel', 'dkms', 'bzip2', 'perl'));
348 if not fRc:
349 reporter.error('Error installing additional installer dependencies');
350 else:
351 reporter.error('Installing Linux Additions for kind "%s" is not supported yet' % oTestVm.sKind);
352 return (False, oTxsSession);
353
354 if fRc:
355 #
356 # The actual install.
357 # Also tell the installer to produce the appropriate log files.
358 #
359 fRc = self.txsRunTest(oTxsSession, 'VBoxLinuxAdditions.run', 5 * 60 * 1000,
360 '/bin/sh', ('/bin/sh', '${CDROM}/VBoxLinuxAdditions.run'));
361 if not fRc:
362 reporter.error('Installing Linux Additions failed (see log file for details)');
363
364 #
365 # Download log files.
366 # Ignore errors as all files above might not be present for whatever reason.
367 #
368 asLogFile = [];
369 asLogFile.append('/var/log/vboxadd-install.log');
370 self.txsDownloadFiles(oSession, oTxsSession, asLogFile, fIgnoreErrors = True);
371
372 if fRc:
373 (fRc, oTxsSession) = self.txsRebootAndReconnectViaTcp(oSession, oTxsSession, cMsTimeout = 3 * 60000);
374
375 return (fRc, oTxsSession);
376
377 def testIGuest_additionsVersion(self, oGuest):
378 """
379 Returns False if no version string could be obtained, otherwise True
380 even though errors are logged.
381 """
382 try:
383 sVer = oGuest.additionsVersion;
384 except:
385 reporter.errorXcpt('Getting the additions version failed.');
386 return False;
387 reporter.log('IGuest::additionsVersion="%s"' % (sVer,));
388
389 if sVer.strip() == '':
390 reporter.error('IGuest::additionsVersion is empty.');
391 return False;
392
393 if sVer != sVer.strip():
394 reporter.error('IGuest::additionsVersion is contains spaces: "%s".' % (sVer,));
395
396 asBits = sVer.split('.');
397 if len(asBits) < 3:
398 reporter.error('IGuest::additionsVersion does not contain at least tree dot separated fields: "%s" (%d).'
399 % (sVer, len(asBits)));
400
401 ## @todo verify the format.
402 return True;
403
404 def testIGuest_additionsRunLevel(self, oGuest, oTestVm):
405 """
406 Do run level tests.
407 """
408 if oTestVm.isLoggedOntoDesktop():
409 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Desktop;
410 else:
411 eExpectedRunLevel = vboxcon.AdditionsRunLevelType_Userland;
412
413 ## @todo Insert wait for the desired run level.
414 try:
415 iLevel = oGuest.additionsRunLevel;
416 except:
417 reporter.errorXcpt('Getting the additions run level failed.');
418 return False;
419 reporter.log('IGuest::additionsRunLevel=%s' % (iLevel,));
420
421 if iLevel != eExpectedRunLevel:
422 pass; ## @todo We really need that wait!!
423 #reporter.error('Expected runlevel %d, found %d instead' % (eExpectedRunLevel, iLevel));
424 return True;
425
426
427 def testGuestProperties(self, oSession, oTxsSession, oTestVm):
428 """
429 Test guest properties.
430 """
431 _ = oSession; _ = oTxsSession; _ = oTestVm;
432 return True;
433
434if __name__ == '__main__':
435 sys.exit(tdAddBasic1().main(sys.argv));
Note: See TracBrowser for help on using the repository browser.

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